ffmpeg 按视频时间而不是挂钟时间进行分段

ffmpeg 按视频时间而不是挂钟时间进行分段

我有一个将视频录制到磁盘的系统,有时系统会出现错误。我试图在实验室中重新创建录制系统,不使用实际的相机(它很贵,而且没有备用相机),以尝试复制导致错误的使用模式。

我在驯服 ffmpeg 时遇到了麻烦。

背景:

使用以下命令从所连接摄像机提供的 rtsp:// URL 在一个线程中连续捕获视频:

ffmpeg -i rtsp://192.168.0.10/h264 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -segment_atclocktime 1 -strftime 1 /tmp/capture-%s.mp4

这项功能可以正常运行并生成预期时长为 15 分钟的视频文件。

问题:

在实验室中,我没有摄像头,也没有 rtsp:// 流。相反,我从真实系统复制了一个捕获的 MP4,并将其用作 ffmpeg 的输入。类似于:

ffmpeg -stream_loop -1 -i capture-1469547000.mp4 -c copy -map 0 -f segment **-{NEED PARAM}** -segment_format mp4 -strftime 1 /tmp/captest-%s.mp4

-stream_loop -1参数执行预期操作:它从输入文件(持续时间为 15 分钟)读取并生成无限输出流。这是从 rtsp:// 流读取的合理近似值。

我不知道该使用什么参数才能使这个实验室系统像真实系统一样将视频分割成 15 分钟的片段。我期望的是输出文件序列,每个文件的大小与输入文件大致相同。

尝试 #1

使用-segment_time 900似乎要么 a) 想要使用 15 分钟的挂钟值,要么 b) 被忽略。由于从现有 MP4 复制比从 rtsp:// 流复制要快得多,因此生成的捕获文件是原始文件的很多副本。

尝试#2

我用了这个命令

ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 capture-1469547000.mp4

确定输入文件有 13494 帧。

使用-segment_frames 13494似乎被忽略了,并且输出根本没有分段。

尝试#3

我已阅读了大量 ffmpeg 文档,但要么缺少我需要的内容,要么它不存在。

使用-ss *position* -t *duration*不会进行连续记录和分段输出。

请求帮助

我应该使用哪些参数来使分割 a) 起作用并且 b) 达到 15 分钟的视频时长?

可能的并发症

示例 MP4 中的时间戳(DTS?)并不“好”,因为会持续产生此错误:

[段@0x2abc7c0] 输出流 0:0 中的非单调 DTS;之前:80990160,当前:-74730276972;更改为 80990161。这可能会导致输出文件中的时间戳不正确。  
DTS 191648787,下一个:-830336344130 st:0 无效删除  
PTS 191648787,下一个:-830336344130 无效删除 st:0

但是,我不需要生成的视频文件真正播放或保持完整,因此我会忽略这一点,除非它影响我需要重新创建的分割。

更多信息

ffmpeg 版本:

\# /usr/share/local/bin/ffmpeg -版本  
ffmpeg 版本 N-79587-g9f9c833 版权所有 (c) 2000-2016 FFmpeg 开发人员  
使用 gcc 4.8 构建(Ubuntu/Linaro 4.8.2-16ubuntu4)  
配置:--prefix=/home/t/dev/j/third-party/ffmpeg/../build--cross-prefix=/usr/bin/arm-linux-gnueabihf--cpu=armv7-a--disable-shared--enable-static--enable-gpl--enable-pthreads--enable-nonfree--enable-libx264--enable-filters--extra-libs=-static--extra-cflags=--static--enable-cross-compile--target-os=linux--disable-inline-asm--arch=armv7--disable-debug--disable-altivec--disable-sse--disable-armv6--disable-armv6t2--disable-mmx--disable-neon--disable-amd3dnow--disable-thumb--extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/../build/lib --extra-cflags=-I/home/t/dev/j/third-party/ffmpeg/../build/include --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavcodec --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavdevice --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavfilter --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavformat --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavresample --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libavutil --extra-ldflags=-L/home/t/dev/j/third-party/ffmpeg/libswscale --extra-ldflags=-lx264 --extra-ldflags=-lm --extra-ldflags=-ldl --extra-cflags='-fpic -mthumb'  
libavutil 55. 22.101 / 55. 22.101  
libavcodec 57. 38.100 / 57. 38.100  
libavformat 57. 34.103 / 57. 34.103  
libavdevice 57. 0.101 / 57. 0.101  
libavfilter 6. 44.100 / 6. 44.100  
libswscale 4. 1.100 / 4. 1.100  
libswresample 2. 0.101 / 2. 0.101  
libpostproc 54. 0.100 / 54. 0.100

答案1

segment_time应该可以工作。它指的是片段持续时间,而不是挂钟。

关键帧的放置可能会造成阻碍,因此请尝试

ffmpeg -fflags +genpts -i capture-1469547000.mp4 -c copy -map 0 -f segment -segment_time 900 -segment_format mp4 -break_non_keyframes 1 -strftime 1 /tmp/capture-%s.mp4

我删除了 stream_loop 选项,因为目前存在与其使用相关的时间戳生成错误。这也可能会造成干扰。

如果需要处理非常长的流,请使用 concat 解复用器。

创建文本文件

file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'
file 'capture-1469547000.mp4'

然后使用

ffmpeg -f concat -i list.txt -c copy ...

答案2

我有一个可行的解决方案。

根本原因

我保存的样本捕获文件结果并不“适合”我想要的目的(无限输入流),尽管除此之外它是一个很好的视频文件(虽然无法搜索,但可以播放)。问题似乎与时间戳有关,也可能与段复用器存在一个或多个错误有关。

解决方案

我跑了

ffmpeg -i capture-1469547000.mp4 -c copy captemp.mp4

相反,使用captemp.mp4stream_loop 或 concat muxer 我可以获得良好的流。

我不确定 capture-1469547000.mp4 和 captemp.mp4 之间有什么区别;AtomicParsley 显示 captemp.mp4 在“elst”原子中短了 12 个字节。

再次查看我原来的设置,并添加内容segment_list后发现:段生成正确,但速度非常快。它们只是被附加到现有的段文件中,而不是生成新的段文件。这部分是...的错

strftime 潜在错误

我使用的strftime是带%s格式的格式。结果发现 strftime 使用的是主机的时钟时间,而不是视频片段内的时间。即使在“工作”情况下也是如此;我已改为使用片段复用器的%d格式。

这可能是一个错误,也是为什么在非工作情况下各个段会相互附加的原因。

我相当确定使用该-re标志可以通过减慢处理速度来解决这个问题,但我实际上想要加速处理。所以我还没有尝试过。

相关内容