显示标签为“多媒体”的博文。显示所有博文
显示标签为“多媒体”的博文。显示所有博文

2014年4月14日星期一

我常用的Kdenlive编码方案

第一个是最常用的 H.264 VBR。
f=matroska hq=1 acodec=flac ar=44100 pix_fmt=yuv420p vcodec=libx264 vprofile=high 8x8dct=1 level=5.1 preset=veryslow flags=+loop vb=%bitrate+'k' aspect=%dar pass=%passes
由于Kdenlive 0.9.6没办法调用libfdk_aac编码器,音频我用了flac。之后再用FFmpeg转一下libfdk_aac。
ffmpeg -i INPUT.mkv -c:v copy -c:a libfdk_aac -profile:a aac_he -b:a 128k OUTPUT.mkv

第二个是 H.264 CRF。
f=matroska hq=1 acodec=flac ar=44100 pix_fmt=yuv420p vcodec=libx264 vprofile=high 8x8dct=1 level=5.1 preset=veryslow flags=+loop vcrf=22 aspect=%dar
音频部分处理同上。

第三个是 ProRes。
f=matroska acodec=flac ar=44100 ac=2 vcodec=prores vprofile=3 pix_fmt=yuv422p10le qscale=11 vendor=ap10 aspect=%dar
Kdenlive 0.9.6不仅不能调用libfdk_aac,还不能调用prores_ks。(好像所有带下划线的编码器都不能调用?)所以只好用原版prores了,也就不能用yuv444p10le了。

2014年1月4日星期六

Linux下流畅地录屏

用过很多Linux下的录屏工具,基本分成三类,FFmpeg 后端、GStreamer 后端、自己实现后端。有很多录屏软件让我不满意。有的在高分辨率下有很严重的跳帧问题,最终导致音画不同步。有的不支持录制系统的声音。还有的没有精细的配置功能。而且,我希望能够输出无损压缩的媒体格式,便于后期处理。
分享我的屏幕录制命令如下:
sleep 5; ffmpeg -y -f x11grab -s 1920x1080 -framerate 30 -i :0 -vf 'setpts=(RTCTIME-RTCSTART)/(TB*1000000)' -c:v libx264 -profile:v high444 -preset:v veryfast -qp:v 0 -pix_fmt yuv444p screencast.mkv
要注意以下几点:
-s 1920x1080 换成自己的屏幕分辨率,
-framerate 30 换成录屏的帧率,
-i :0 换成当前的 $DISPLAY 环境变量值,
-i alsa_output.xxxxxxxxxxxxx.0.analog-stereo.monitor 的参数,请看下面。
这样录制下来的视频文件是 H.264 YUV444P 无损的,便于后期剪辑。如果要分享到互联网,请在二次压制的时候加上 -pix_fmt 420p,因为很多网络媒体播放器不支持 YUV444P。sleep 5 是给自己准备最小化终端窗口的时间。

录制系统声音

再加一个 PulseAudio 的输入:
sleep 5; ffmpeg -y -f x11grab -s 1920x1080 -framerate 30 -i :0 -f pulse -i alsa_output.xxxxxxxxxxxxx.0.analog-stereo.monitor -vf 'setpts=(RTCTIME-RTCSTART)/(TB*1000000)' -af asetpts=N/SR/TB,apad -shortest -c:v libx264 -profile:v high444 -preset:v veryfast -qp:v 0 -pix_fmt yuv444p -c:a flac screencast.mkv
-i alsa_output.xxxxxxxxxxxxx.0.analog-stereo.monitor 的获取方法如下:
执行 pactl list | grep -A2 'Source #',会看到如下两行(如果你只有一块声卡的话):
Source #0
        State: IDLE
        Name: alsa_output.xxxxxxxxxxxxx.0.analog-stereo.monitor
--
Source #1
        State: SUSPENDED
        Name: alsa_output.xxxxxxxxxxxxx.0.analog-stereo
Name 后面有 .monitor 的表示系统声音,另一个表示麦克风。

音画同步问题

如果出现音画不同步,请尝试 -af 指定以下几种参数的组合:
-af aresample=async=1
-af asetpts=N/SR/TB,apad -shortest
-af 'asetpts=(RTCTIME-RTCSTART)/(TB*1000000)'

跳帧问题

如果遇到跳帧,可以适当降低帧率,设置 -threads auto;或者将 -preset:v veryfast 换成 -preset:v ultrafast;或者试试看 FFv1、FFvHuff、HuffYUV 等无损编码器和 MPEG1Video、MPEG2Video、MJPEG 等复杂度低的编码器,或者把音频编码器换成 pcm_s16le;或者换用 MPEG-TS、FLV 等容器格式。
还可以试试看 Apple ProRes 编码器。它有着很快的速度和接近无损的效果。FFmpeg 自带三个 ProRes 编码器(prores、prores_aw、prores_ks)和两个解码器(prores、prores_lgpl)。这些编解码器性能不同,功能各异,请自己尝试参数配置。
如果录屏让你的 SCSI 硬盘不堪重负,请检查 SCSI 控制器是否在 AHCI 模式而不是 IDE 模式。(如果你已经安装了 Linux 或 *BSD 以外的系统,请不要修改 SCSI 模式;我的 7200rpm 笔记本电脑硬盘在 IDE 模式下只有 25MiB/s 的写入速度,而切换到 AHCI 模式下有 90MiB/s 写入速度。)
如果有以上方法都不能解决的音画同步问题,建议使用两个独立的 FFmpeg 进程来分别录制图像和声音。但是会带来后期处理的麻烦。

后期压制

将输出的 screencast.mkv 压制成 MP4 输出并分享到网络,可以用类似这样的命令:
ffmpeg -i screencast.mkv -movflags +faststart -c:v libx264 -profile:v high -level:v 4.1 -preset:v veryslow -b:v 4096k -pix_fmt yuv420p -c:a libfdk_aac -profile:a aac_he -b:a 256k my_screencast.mp4
其中 -c:a libfdk_aac 根据自己的 AAC 编码器来修改(但是只有 libfdk_aac 支持 -profile:a aac_he,而且质量最好),如果不知道自己装了哪些编码器,就依次尝试:
-c:a libfdk_aac
-c:a libfaac
-c:a aac -strict -2
如果 QuickTime/MP4 文件要通过网络分享,建议使用 -movflags +faststart 参数。它把关键数据移动到文件开头,有利于缓冲。

2013年11月15日星期五

Linux下用Mencoder转录VCD

有一些 VCD 光碟在 Windows 下可以直接通过复制 /MPEGAV/AVSEQ*.DAT 来转录。而到了 Linux 下面会发现有时可以,有时不可以。
那么,既然 MPlayer 可以播放 VCD,Mencoder 就可以转录 VCD。
用下面的命令:
mencoder -o AVSEQ01.mpg -of mpeg -ovc copy -oac copy vcd://1
斜体字的“01”可以提换成轨道编号。

送给有需要的人。

2013年10月2日星期三

无损合并视频的多种方法

众所周知,从某些视频网站下载的视频是分段的。比如新浪视频每隔6分钟分段,俗称“6分钟诅咒”。
现在的任务是将这些视频片段合并起来,并且尽量无损。

方法一:FFmpeg concat 协议

对于 MPEG 格式的视频,可以直接连接:
ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy output.mpg
对于非 MPEG 格式容器,但是是 MPEG 编码器(H.264、DivX、XviD、MPEG4、MPEG2、AAC、MP2、MP3 等),可以包装进 TS 格式的容器再合并。在新浪视频,有很多视频使用 H.264 编码器,可以采用这个方法
ffmpeg -i input1.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input1.ts
ffmpeg -i input2.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input2.ts
ffmpeg -i input3.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input3.ts
ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy -bsf:a aac_adtstoasc -movflags +faststart output.mp4
保存 QuickTime/MP4 格式容器的时候,建议加上 -movflags +faststart。这样分享文件给别人的时候可以边下边看。

方法二:FFmpeg concat 分离器

这种方法成功率很高,也是最好的,但是需要 FFmpeg 1.1 以上版本。先创建一个文本文件 filelist.txt:
file 'input1.mkv'
file 'input2.mkv'
file 'input3.mkv'
然后:
ffmpeg -f concat -i filelist.txt -c copy output.mkv
注意:使用 FFmpeg concat 分离器时,如果文件名有奇怪的字符,要在 filelist.txt 中转义。

方法三:Mencoder 连接文件并重建索引

这种方法只对很少的视频格式生效。幸运的是,新浪视频使用的 FLV 格式是可以这样连接的。对于没有使用 MPEG 编码器的视频(如 FLV1 编码器),可以尝试这种方法,或许能够成功。
mencoder -forceidx -of lavf -oac copy -ovc copy -o output.flv input1.flv input2.flv input3.flv

方法四:使用 FFmpeg concat 过滤器重新编码(有损)

语法有点复杂,但是其实不难。这个方法可以合并不同编码器的视频片段,也可以作为其他方法失效的后备措施。
ffmpeg -i input1.mp4 -i input2.webm -i input3.avi -filter_complex '[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1 [v] [a]' -map '[v]' -map '[a]' <编码器选项> output.mkv
如你所见,上面的命令合并了三种不同格式的文件,FFmpeg concat 过滤器会重新编码它们。注意这是有损压缩。
[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] 分别表示第一个输入文件的视频、音频、第二个输入文件的视频、音频、第三个输入文件的视频、音频。concat=n=3:v=1:a=1 表示有三个输入文件,输出一条视频流和一条音频流。[v] [a] 就是得到的视频流和音频流的名字,注意在 bash 等 shell 中需要用引号,防止通配符扩展。

提示

  1. 以上三种方法,在可能的情况下,最好使用第二种。第一种次之,第三种更次。第四种是后备方案,尽量避免。
  2. 规格不同的视频合并后可能会有无法预测的结果。
  3. 有些媒体需要先分离视频和音频,合并完成后再封装回去。
  4. 对于 Packed B-Frames 的视频,如果封装成 MKV 格式的时候提示 Can't write packet with unknown timestamp,尝试在 FFmpeg 命令的 ffmpeg 后面加上 -fflags +genpts

参考资料

  1. http://trac.ffmpeg.org/wiki/How to concatenate (join, merge) media files
  2. http://ubuntuforums.org/showthread.php?t=956769