前言
ffmpeg是一个非常厉害的音频、视频处理工具,它开源且几乎没用使用限制。ffmpeg本身可以单独运行,前提是你熟悉它的内置命令语法。通常情况下,我们不会直接使用ffmpeg的命令行去进行音频、视频处理,我们一般都会对其进行功能封装进行二次开发应用。今天我们就来聊聊如何在TCL中调用ffmpeg并实现桌面录屏功能。
ffmpeg桌面录屏命令
ffmpeg本身设计了一套命令,通过这些命令你可以发挥ffmpeg最大能力。这套命令实际上设计的还是比较复杂的,要完整掌握需要花上一段时间认真的学习,同时还需要具备一定的计算机音视频理论基础。本文不过多介绍ffmpeg其它的能力,仅仅针对录屏需要来介绍相关命令语法。
由于ffmpeg本身是c语言编写,它具有跨平台特性,但是在不同的操作系统中使用的命令语法会有些许差别。现在我们以在windows系统下为例给出如下录屏命令:
ffmpeg -y -f gdigrab -framerate 20 -i desktop -vcodec libx264 -pix_fmt yuv420p -preset ultrafast -f segment -segment_list vd1.txt -segment_list_type ffconcat -segment_time 3600 -segment_format mp4 vd1_%02d.mp4
命令看上去有些长,但是不妨碍我们去理解它,下面我将逐个解释命令中每个部分的意义。
首先命令的第一个单词是ffmpeg,它作为ffmpeg命令名出现在命令的开始位置。
-y:指示ffmpeg,自动覆盖输出文件,无需用户确认。
-f gdigrab:指定输入设备为 gdigrab
,这是 Windows 平台下基于 GDI 的屏幕抓取工具,用于捕获桌面或特定窗口的内容。
-framerate 20:设置帧率为每秒 20 帧(fps),即每秒录制 20 张画面。
-i desktop:指定输入源为整个桌面(全屏录制)。如果要录制特定窗口,可以替换为窗口句柄(HWND)或使用 -window_id
参数。
-vcodec libx264:使用 libx264
编码器进行视频编码,这是广泛使用的 H.264 编码器,具有高压缩率和良好的兼容性。
-pix_fmt yuv420p:设置像素格式为 yuv420p
,这是最通用的 YUV 格式,支持大多数播放器和平台。
-preset ultrafast:设置编码速度为“超快”,牺牲压缩效率以提高编码速度,适合实时录制场景。
-f segment: 启用分段输出模式,将视频分割为多个文件。
-segment_list vd1.txt:生成一个名为 vd1.txt
的索引文件,记录所有分段视频文件的路径。
-segment_list_type ffconcat:指定索引文件类型为 ffconcat
,这是 FFmpeg 支持的一种简单拼接格式。
-segment_time 3600:每个分段视频的时长为 3600 秒(1 小时),超过该时间后会创建新文件。
-segment_format mp4:每个分段视频的格式为 MP4。
vd1_%02d.mp4:输出文件名模板,%02d
表示两位数字的序号(如 vd1_00.mp4
, vd1_01.mp4
等)。
通过上面各个参数的介绍,你应该明白这条命令在让ffmpeg干啥。本文要实现的是通过TCL调用ffmpeg实现桌面录屏功能,下面我们将介绍如何在TCL中调用该命令。
TCL调用ffmpeg
我们有篇博文曾经介绍过如果使用TCL调用Python,这里使用的方法原理上与之一致,利用的就是TCL的管道通信(Pipe)。下面我们同样给出一个示例代码:
proc startRecordScreen {recordfolder} {
set pchanel ""
set outFilePath [file join $recordfolder VD_[clock microseconds]]
try {
set pchanel [open |[list ffmpeg -y -f gdigrab -framerate 20 -i desktop -vcodec libx264 -pix_fmt yuv420p -preset ultrafast -f segment -segment_list [file nativename $outFilePath].txt -segment_list_type ffconcat -segment_time 3600 -segment_format mp4 [file nativename $outFilePath]_%02d.mp4] w+]
chan configure $pchanel -buffering line -blocking 0
return "$pchanel $outFilePath"
} on error {em} {
puts $em
return ""
}
}
上面的代码定义了一个名为startRecordScreen的函数,该函数内部首先创建了一个视频路径的文件路径,并将该路径拼接到了ffmpeg录屏命令中。接着创建了一个Pipe管道,用于打通与ffmpeg应用程序的通信,管道创建成功的同时,ffmpeg应用进程也被打开并开始执行上述录屏命令。接下来我们可以通过该管道来控制ffmpeg应用程序,比如在管道中输入“q”,便可以结束录屏,并退出ffmpeg应用程序。
vd1_00
总结
没错,仅仅就是上面的几行代码就实现了通过TCL调用ffmpeg实现了屏幕录屏功能。这也充分体现了TCL代码的简洁优雅。