将非标准纵横比的视频文件刻录到 DVD

Fah*_*tha 7 dvd ffmpeg burning

将视频文件刻录到 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
Run Code Online (Sandbox Code Playgroud)

注意:--title设置 DVD 的标题,-T设置目录。在以上两个命令中,-o 开关都引用了一个目录,而不是实际的 dvd。

# 3. roll the .mpg file into an ISO file
genisoimage -dvd-video -o dvdimage.iso dvd
Run Code Online (Sandbox Code Playgroud)

最后,将生成的 iso 文件刻录到空白 DVD。我使用 Brasero,这是可靠的。

但是,此方法不适用于非标准纵横比。DVD 格式在指定可接受的纵横比方面非常严格。如果 dvdauthor 说类似的话,你就会知道你是否有这个问题

WARN: unknown mpeg2 aspect ratio 1
Run Code Online (Sandbox Code Playgroud)

修改此方法以处理非标准纵横比的好方法是什么?

更新:感谢 Anthony 非常彻底和明确的答案。我希望这对那些试图为这个令人烦恼的问题寻找答案的人有用。我不知道网络上对此有任何其他明确的解释。

der*_*ert 6

基本方法是为您的视频添加黑色边框,使其适合 DVD 允许的宽高比之一。

TLDR:跳到结论。

几个定义

不过,首先,我需要定义几个不同的东西:

  • 一个宽高比是简单的东西通过高度,通常表示为分数除以宽度。通常传统的斜线被冒号代替:我们写 4:3 而不是4 ? 3 . 有时,这些以十进制表示(1.333...)。您也可以将其称为 8:6、12:9、16:12 等,因为它们都是平等的。甚至是 1.333:1(相等,只要你能写出足够多的 3 秒)。
  • 显示宽高比(DAR)是实际显示的(例如,TV)的纵横比。常见的显示器标称是 4:3 或 16:9。
  • 存储的纵横比(SAR)是宽度与高度所存储的图像或视频的比率(以像素为单位)。例如,NTSC DVD 视频的最大分辨率为 720 x 480(“Full D1”),其 SAR 为 1.5:1。
  • 像素纵横比是在所存储的图像的单个像素的纵横比。在视频中,像素并不总是方形的。当非方形时,它们通常窄于高。

以上三者之间存在简单的数学关系: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),并带有 8 像素黑条。如果被切掉的边没问题,那么您可以使用完整的 720x480。无论哪种方式,您都需要根据需要缩放视频以获得 10:11(4:3 的 DAR)或 40:33(16:9 的 DAR)的 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'"
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

注意有三个过滤器有:scalepad,和setsar。我们将依次从最后开始,因为最后的那些是最简单的。

最后一个过滤器令人困惑,直到您检查文档 (`man ffmpeg-filter) 并找到删除的这条咒骂行:““setsar”过滤器设置过滤器输出视频的样本(又名像素)纵横比。” 所以这实际上是将 PAR 设置为 40:33,这是我们在上面所说的我们想要使用的值。

pad过滤器添加黑色边框。文档告诉我们ow是输出宽度(即 720,距w=720零件),,输出高度(即,距h=480零件480 )。iwih分别是输入宽度和高度。ow - iw因此是我们添加到宽度上的像素数(类似地oh - ih表示高度);除以 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?¹是PAR的倒数,即33/40。

  • dar是一个 ffmpeg 变量。它是输入视频的 DAR。

  • 理解这一点的关键是中间的计算,我们有一个计算,即 «H» × dar ÷ «PAR»。请记住,dar 是原始视频的显示 w/h。因此,将目标宽度(以像素为单位)乘以 dar 可以得出如果我们缩放视频以具有目标高度 «H» 和方形像素的宽度。除以 PAR 然后将其转换为我们实际使用的非方形像素的宽度。

-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'"
Run Code Online (Sandbox Code Playgroud)

示例:假设您拍摄了一个 1280 x 720 像素的视频,显示宽高比为 16:9。从中间开始:

  1. «H»*«PAR?¹»*dar = 480*33/40*16/9 = 704。
  2. 704 / 2 = 352。
  3. 截断(352 + 0.5)= 352
  4. 352 * 2 = 704
  5. 分钟(720、704)= 704

这是完整的可用宽度(即,不包括 8px 的不可用区域),正如我们对 16:9 显示器上的 16:9 视频所期望的那样。

当我们在高度上做它时,我们得到 490,这要归功于 min() 保持为 480。但实际上,这表明我们可能想在那里使用 704(可用宽度)而不是 720,这正是480. 所以看起来那里有一个小错误,导致一个微小的(可能是难以察觉的)失真。我相信这在下面是固定的。

综上所述

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
))
Run Code Online (Sandbox Code Playgroud)

注意:较旧的 ffmpeg 没有-filter:v. 您可以尝试-vf(未经测试),或者更好的是从ffmpeg.org下载新的静态构建。