我有大量的jpg图片,希望将它们无损地转换为视频(或者,至少,只要编码时间不比其他时间长很多,就非常接近无损地)。
天真的,我认为应该有一些编解码器可以按原样存储每个单独的jpg帧(无需重新压缩),并且也许可以通过仅用前一帧的增量信息替换某些帧来实现一些不错的压缩。在我的情况下,有许多帧序列彼此相同,或者它们之间的差别很小。
ffmpeg是否有一些编解码器和合适的设置可以实现这一目标?
我有大量的jpg图片,希望将它们无损地转换为视频(或者,至少,只要编码时间不比其他时间长很多,就非常接近无损地)。
天真的,我认为应该有一些编解码器可以按原样存储每个单独的jpg帧(无需重新压缩),并且也许可以通过仅用前一帧的增量信息替换某些帧来实现一些不错的压缩。在我的情况下,有许多帧序列彼此相同,或者它们之间的差别很小。
ffmpeg是否有一些编解码器和合适的设置可以实现这一目标?
Answers:
您只需将JPG图像多路复用即可制作视频:
ffmpeg -framerate 30 -i input%03d.jpg -codec copy output.mkv
请注意,如果省略,-framerate
则默认值-framerate 25
将应用于输入。
您可以用来jpegtran
对每个帧执行无损优化,这可以节省大量文件:
mkdir outputdir
for f in *.jpg; do jpegtran -optimize -copy none -perfect -v "$f" > "outputdir/$f"; done
现在与ffmpeg
上面所示的多路复用。
该framehash复用器可以用来比较每个帧的唯一哈希值,以确保结果是真正的无损:
$ ffmpeg -i input%03d.jpg -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
$ ffmpeg -i output.mkv -map 0:v -f framehash -
stream_index, packet_dts, packet_pts, packet_duration, packet_size, hash
0, 0, 0, 1, 460800, 29bcc2db3726c7dfec1826c5740f603f
0, 1, 1, 1, 460800, b5fdc23d93cbd043dc2b9290dc8378f0
0, 2, 2, 1, 460800, ee0709942f24b458fd2380d134dcb59d
...
在以上示例中,输入和输出的每个关联帧共享相同的哈希值,以确保帧相同且输出无损。
framemd5
命令除了列出哈希值之外还应该实现什么?这样确定相同的帧后,如何获得额外的压缩?
这将输出无损的H.264视频,其中帧将使用其他帧中的信息
ffmpeg -f image2 -r 30 -i %09d.jpg -vcodec libx264 -profile:v high444 -refs 16 -crf 0 -preset ultrafast a.mp4
选项说明:
-f image2
-告诉ffmpeg选择一组图像-r 30
-告诉ffmpeg以每秒30帧(或图像)的速度编码(将其更改为所需的帧率)-i %09d.jpg
-告诉ffmpeg使用图像000000000.jpg至999999999.jpg作为输入。更改9
中%09d.jpg
有多少个零的图像序列的名字了。如果您的文件名是例如img0001.jpg,则它将表示为img%04d.jpg-vcodec libx264
-告诉ffmpeg输出到H.264兼容文件-profile:v high444
-告诉libx264使用高4:4:4预测无损配置文件,允许无损编码-refs 16
-告诉libx264将16张图像存储在缓冲区中,以便视频中的其他图像可以引用它们-crf 0
-告诉libx264执行无损编码-preset ultrafast
-告诉libx264将编码速度优先于输出文件大小a.mp4
-告诉ffmpeg将输出保存在名为a.mp4的MP4文件中。将此更改为您要使用的文件名和格式-refs 5
在MOST,除非您知道您的内容具有相同的图像,并用其他图像分开,否则可能会导致x264在到达重复项之前丢失引用。高于ultrafast
使得无损模式略有不同,比CABAC的约10%的涨幅比CAVLC(在无损所需要的比特率较高的CPU成本)等。严重的是,在一些实况转播的720x480p60(去隔行输出)上,容量superfast
为28GB,slower
容量为27GB。如果编码时间无关紧要,而解码时间无关紧要,请确保避免使用CABAC。甚至可能-tune fastdecode
。适中的引用计数不应该受到影响。
-preset placebo
百分之几的额外费用。
-vcodec libx265 -x265-params lossless=1
是等效选项。(但是以我的经验(=录制Powerpoint幻灯片演示文稿),它不一定更好,并且比h264慢得多)请继续关注明年的AOMedia的AV1 / IETF的NETVC1 / Xiph的Daala /届时将如何重命名...的无损模式
您可以创建一个avi
动画作为一个系列的png
图像(png
是无损的,因此jpeg => png
转换不应降低您的图片):
如果您的图片名为 img_0001.jpg
ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec png video.avi
其中“ 25”是您想要的结果视频中的帧频。-start_number
如果为1,则不需要。但是如果您的第一个视频编号不是1,则很有用。
如果要以mjpeg
最高质量进行编码,则命令行为:
ffmpeg -r 25 -start_number 1 -f image2 -i "img_%04d.jpg" -vcodec mjpeg -qscale 1 video.avi
事情的好处是您可以将视频转换回一系列图片:
ffmpeg -i video.avi "img_series_%04d.png"
ffmpeg -i video.avi "img_series_%04d.jpg"
等等...
要扩展LordNeckbeard的答案,是的,只需将JPEG数据混合到MJPEG视频流中即可。这将是输出图像精确序列的最小表示,即使MJPEG在当今的标准下效率极低。(没有时间冗余,甚至没有任何帧内预测。
您可以制作可变帧率的MJPEG视频,以利用输入中的重复图像。
ffmpeg -framerate 30 -i input%03d.jpg -vf mpdecimate -codec copy output.mkv # doesn't work.
嗯,这是行不通的,因为mpdecimate不适用于压缩数据,并且我们不能让ffmpeg解码然后重新jpeg图像数据而不会造成损失和CPU成本。
也许如果您将重复的jpg源文件替换为具有该序列号的空文件,或者其他内容?
由于这个问题还不是最近的,除非有人回答问如何做,否则我不会花时间去弄清楚该怎么做。但是由于MJPEG可以放入mkv容器中,因此我敢肯定,有一个文件不会对重复帧重复jpeg数据,而只是没有输出帧要解码,直到重复序列被过度。
哦,这是个主意:
ffmpeg -framerate blah -input blah -vf mpdecimate -f mkvtimestamp_v2 mpdecimate.timestamps
然后删除(或移开)mpdecimate要删除的帧的所有jpeg(可能有一些日志记录选项?或-vf showinfo,然后对其进行解析,然后仅移动或硬链接显示在其输出中的帧,留在后面丢弃的JPEG?)。将其多路复用到MJPEG.mkv,然后使用mkvmerge进行一些操作,将其中的帧时间戳替换为中的时间戳mpdecimate.timestamps
。
如果您使用的是xcoding,而不是仅仅将jpeg数据混合到MJPEG,这将更加容易,因为您只需将我的第一个命令与mpdecimate和除以外的任何编解码器一起使用copy
,它将可以正常工作(tm)。
我没有尝试过任何一个,因为这是一个老问题。这也是我没有填补如何基于mpdecimate输出实际过滤jpeg目录或如何实际使用时间戳流的空白的原因。