将视频文件刻录到 DVD 的标准 Unixy 命令行方法如下(假设)
# 1. First use ffmpeg to convert to an mpg file.
ffmpeg -i input.m4v -target ntsc-dvd output.mpg
# 2. now do the authoring
dvdauthor --title -o dvd -f output.mpg
dvdauthor -o dvd -T
注意:--title
设置 DVD 的标题,-T
设置目录。在上述两个命令中,-o 开关引用的是目录,而不是实际的 DVD。
# 3. roll the .mpg file into an ISO file
genisoimage -dvd-video -o dvdimage.iso dvd
最后,将生成的 iso 文件刻录到空白 DVD 上。我用的是Brasero,很可靠。
但是,此方法不适用于非标准纵横比。 DVD 格式对于指定可接受的宽高比非常严格。如果 dvdauthor 说类似的话,您就会知道是否遇到此问题
WARN: unknown mpeg2 aspect ratio 1
修改此方法以处理非标准纵横比的好方法是什么?
更新:感谢安东尼的非常彻底和清晰的回答。我希望这对那些试图找到这个棘手问题答案的人有用。我不知道网上对此有任何其他明确的解释。
答案1
基本方法是向视频添加黑色边框,使其符合 DVD 允许的宽高比之一。
TLDR:跳至综上所述。
一些定义
不过,首先我需要定义几个不同的东西:
- 一个纵横比只是某个物体的宽度除以高度,通常表示为分数。通常传统的斜杠会被冒号取代:我们写 4:3 而不是4 ⁄ 3。有时,这些以十进制表示(1.333…)。您也可以将其称为 8:6、12:9、16:12 等,因为它们都是相等的。甚至 1.333:1(相等,只要你能写出足够的 3)。
- A展示纵横比(DAR) 是实际显示器(例如电视)的宽高比。常见的显示器名义上为 4:3 或 16:9。
- A贮存纵横比(SAR) 是存储的图像或视频的宽度与高度(以像素为单位)的比率。例如,NTSC DVD 视频的最大分辨率为 720 x 480(“Full D1”),其 SAR 为 1.5:1。
- A像素纵横比是存储图像中单个像素的长宽比。在视频中,像素是不是总是方形的。当非正方形时,它们通常比高度窄。
上述三者之间有一个简单的数学关系:SAR × PAR = DAR。例如,720:480 * 8:9 = 4:3。这就是以全分辨率播放在 DVD 上的 4:3 显示屏视频。
另一种复杂性
模拟电视没有像素。相反,它具有连续变化的信号。该信号的某个部分应该被投影到显示器的每一行上,然后有一个非活动时间以允许例如移动到下一行。不过,不同的电视显示的每行数量略有不同,并且在电视的使用寿命内,甚至在电视预热时,这可能会有所不同。
DVD说不要使用最左和最右的8个像素。因此,在 720 中,应该使用 704。每边 8 个像素应该用黑色填充。指定的 PAR 是这个 10:11。
当然,习惯了数字设备的人会觉得这很愚蠢(用适合有礼貌的公司的话)。许多商业 DVD 版本实际上都使用 720 像素,有些期望 10:11 PAR,有些期望 8:9。 [或类似的 16:9 DAR]。大多数硬件 DVD 播放器使用 10:11,当然它也取决于电视设置。
概括
如果您从希望显示每个像素的视频开始,您可能希望将其调整为 704x480 (SAR 22:15),并带有 8px 黑条。如果切掉的边没问题,那么您可以使用完整的 720x480。无论哪种方式,您都需要根据需要缩放视频以获得 10:11(DAR 为 4:3)或 40:33(DAR 为 16:9)的 PAR,如果小于完整的 720x480 帧,请添加黑色酒吧。
实际上在做
值得庆幸的是,ffmpeg
可以做到这一点。在非官方 ffmpeg 支持论坛上,ks_kalvan 提供 ffmpeg 视频过滤器链对于定位 16:9 DAR:
-filter:v "scale='w=min(720,trunc((480*33/40*dar)/2+0.5)*2):h=min(480,trunc((720*40/33/dar)/2+0.5)*2)',pad='w=720:h=480:x=(ow-iw)/2:y=(oh-ih)/2',setsar='r=40/33'"
这是如何运作的‽
请注意,其中有三个过滤器:scale
、pad
和setsar
。我们将从最后开始依次讨论每个内容,因为最后的内容是最简单的。
最后一个过滤器令人困惑,直到您检查文档(`man ffmpeg-filter)并找到这个脏话被删除行:““setsar”过滤器设置过滤器输出视频的样本(又名像素)长宽比。”因此,这实际上是将 PAR 设置为 40:33,这就是我们上面所说的想要使用的值。
滤镜pad
添加黑色边框。文档告诉我们噢是输出宽度(即 720,来自零件w=720
),哦输出高度(即距离零件 480 h=480
)。伊沃和呃分别是输入的宽度和高度。噢-伊沃因此是我们添加到宽度上的像素数(类似地哦-呃对于高度);除以 2 后,图片的每一边都会得到一半的值。换句话说,我们将图片居中。
过滤scale
器调整视频大小。该w=
选项指定新/输出宽度,h=
选项指定高度。同样,它是一个表达式,但更复杂。宽度和高度公式相同,只是高度和宽度交换。让我们检查一下宽度 ( w=
) 公式:
函数和运算符的文档记录在 中
man ffmpeg-util
。对于正数,trunc(x+0.5)
有一个技巧可以得到四舍五入到最接近的整数,这是 ffmpeg 没有的。基于这个
trunc(x+0.5)
技巧,我们有trunc(x/2+0.5)*2
.当然,x/2 给出了 x 的一半;然后截断将其四舍五入到最接近的整数。将其加倍即可得到最接近的甚至数字。我将使用“W”,其中实际命令使用 720。这是最终的输出宽度(以像素为单位)。同样,用“H”代替 480(最终输出高度)。而不是 40/33,“PAR”,因为这是目标像素长宽比。 PAR⁻1是PAR的倒数,即33/40。
dar
是一个 ffmpeg 变量。它是输入视频的 DAR。理解这一点的关键是中间的计算,其中我们的计算为“H”×dar ÷“PAR”。请记住,dar 是原始视频的显示内容。因此,将目标宽度(以像素为单位)乘以 dar 就可以得出如果我们缩放视频以具有目标高度“H”和方形像素的宽度。除以 PAR,然后将其转换为我们实际使用的非方形像素的宽度。
min(«W», # take the minimum [lesser of] target width and...
trunc( # the truncation of (round to integer towards 0)
(«H»*«PAR⁻¹»*dar) # calculate the wanted output width, see note above
/ 2 + 0.5) * 2 # and get the nearest even number to that
))
示例:假设您拍摄了一个 1280 x 720 像素、显示宽高比为 16:9 的视频。从中间开始:
- «H»*«PAR⁻1»*dar = 480*33/40*16/9 = 704。
- 704 / 2 = 352。
- 截断(352 + 0.5) = 352
- 352 * 2 = 704
- 分钟(720, 704) = 704
这是完整的可用宽度(即,不包括 8px 不可用区域),正如我们对 16:9 显示屏上的 16:9 视频的预期一样。
当我们在高度上执行此操作时,我们得到 490,这要归功于 min() 被保持为 480。但实际上,这表明我们可能想在那里使用 704(可用宽度)而不是 720,这恰好是480. 所以看来那里有一个小错误,导致了微小的(并且可能难以察觉的)失真。我相信这是固定的。
综上所述
ffmpeg -i YOUR-FILE-HERE \
-filter:v "scale='w=min(720,trunc((480*33/40*dar)/2+0.5)*2):h=min(480,trunc((704*40/33/dar)/2+0.5)*2)',pad='w=720:h=480:x=(ow-iw)/2:y=(oh-ih)/2',setsar='r=40/33'" \
-target ntsc-dvd YOUR-OUTPUT-HERE.mpg
笔记:较旧的 ffmpeg 没有-filter:v
.你可以试试-vf
(未经测试),或者更好的是从下载新的静态版本ffmpeg.org。