简体   繁体   English

使用 ffmpeg 修剪 HEVC 视频:正确的持续时间,但 output 文件大小太大

[英]Using ffmpeg to trim HEVC video: correct duration, but output file size too large

I have a digitized 8mm 16fps HEVC.mp4 that I'm trying to split into clips using ffmpeg (5.1.2) on MacOS terminal.我有一个数字化的 8mm 16fps HEVC.mp4,我试图在 MacOS 终端上使用ffmpeg (5.1.2) 将其拆分成剪辑。 The output file trims to the correct duration but the filesize is too large. output 文件修剪到正确的持续时间,但文件大小太大。

ffmpeg -ss 05:09 -i input.mp4 -t 02:19 -an -sn -dn -c copy output.mp4

input.mp4 : 11:56 in duration and 8.24 GB in filesize (bitrate 674251 kbits/s). input.mp4 :持续时间为 11:56,文件大小为 8.24 GB(比特率 674251 kbits/s)。
output.mp4 : 02:19 in duration and 5.15 GB in filesize (too large). output.mp4 :持续时间为 02:19,文件大小为 5.15 GB(太大)。

5.15 GB is the filesize I'd expect for a clip that is 05:09 + 02:19 in duration at input.mp4 's 674251 Kbits/s: 5.15 GB 是我期望在input.mp4的 674251 Kbits/s 下持续时间为 05:09 + 02:19 的剪辑的文件大小:
(05:09+02:19) * 674251 kbits/sec = 5.16 GB (05:09+02:19) * 674251 kbits/sec = 5.16 GB

I've tried various -ss start_pos and -t duration values with similar results.我尝试了各种-ss start_pos-t duration值,结果相似。 The output file is correctly duration in time and unexpectedly ( start_pos + duration )*bitrate in filesize. output 文件的duration时间是正确的,但出乎意料的是 ( start_pos + duration )* 文件大小的比特率。

I've consulted this ShotStack.io article on trimming with ffmpeg and this ffmpeg wiki section on cutting small sections from files.我已经查阅了这篇关于使用ffmpeg修剪的ShotStack.io文章和关于从文件中剪切小部分的ffmpeg wiki部分。 Neither specifically states that the resulting file size will be trimmed to match the duration of the clip, but I'd think that'd be useful.两者都没有具体说明生成的文件大小将被修剪以匹配剪辑的持续时间,但我认为这很有用。

Addendum :附录
My input file has only one keyframe at t=0.000s.我的输入文件在 t=0.000 秒时只有一个关键帧。 Likely the root of all my problems.可能是我所有问题的根源。

ffmpeg stdout : ffmpeg 标准输出

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x14ff04760] Using non-standard frame rate 16384/1024
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    creation_time   : 2021-07-24T11:23:44.000000Z
    encoder         : Lavf58.45.100
  Duration: 00:11:56.13, start: 0.000000, bitrate: 92041 kb/s
  Stream #0:0[0x1](und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], 91715 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 159 kb/s (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:2[0x3](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 159 kb/s (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
  Stream #0:3[0x4](eng): Data: none (tmcd / 0x64636D74)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : TimeCodeHandler
      timecode        : 17:15:11:05
File 'output.mp4' already exists. Overwrite? [y/N] y
[mp4 @ 0x14ff08660] Using non-standard frame rate 16/1
    Last message repeated 1 times
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf59.27.100
  Stream #0:0(und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], q=2-31, 91715 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      creation_time   : 2021-07-24T11:23:44.000000Z
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 4290 fps=0.0 q=-1.0 Lsize= 2988507kB time=00:02:18.93 bitrate=176207.6kbits/s speed= 189x    
video:2988420kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.002924%

ffprobe output.mp4

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x130804080] Using non-standard frame rate 16384/1024
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf59.27.100
  Duration: 00:02:19.31, start: 0.000000, bitrate: 175732 kb/s
  Stream #0:0[0x1](und): Video: hevc (Main) (hvc1 / 0x31637668), yuv420p(tv, bt709/bt709/unknown, progressive), 5120x3840 [SAR 1:1 DAR 4:3], 91304 kb/s, 16 fps, 16 tbr, 16384 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      timecode        : 17:15:11:05
  Stream #0:1[0x2](eng): Data: none (tmcd / 0x64636D74)
    Metadata:
      handler_name    : VideoHandler
      timecode        : 17:15:11:05
Unsupported codec with id 0 for input stream 1

input.mp4 is unusual in that it only has one keyframe at t=0.000s, all others are B-frames (verified with ffprobe ). input.mp4的不寻常之处在于它在 t=0.000s 处只有一个关键帧,所有其他都是 B 帧(已通过ffprobe验证)。

The ffmpeg command is correct and the output is a result of there only being one keyframe. ffmpeg命令是正确的,output 是只有一个关键帧的结果。 When using the -c copy coder, all trims/ splices/cuts have to be made at the prior keyframe, which for this input file is only at t=0.使用-c copy coder 时,所有修剪/拼接/剪切都必须在先前的关键帧处进行,对于此输入文件,它仅在 t=0 时。

input.mp4 and desired trim clip: input.mp4和所需的修剪剪辑:

Frame type:    Ibbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...
Keyframe:      ^
Trim Points:                        |-----------------|
Time:          0                    ^start_pos        ^start_pos+duration

ffmpeg -ss start_pos -i input.mp4 -t duration -c copy output.mp4

output.mp4 : output.mp4 :

Frame type:    Ibbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb???
Keyframe:      ^
Trim Points:                        |-----------------|
Time:          ^-start_pos          0                 ^duration

All frames from start_pos back to the prior keyframe (which in this file is the first frame) have to be included in output.mp4 .start_pos回到前一个关键帧(在此文件中是第一帧)的所有帧都必须包含在output.mp4中。

Decoding of output.mp4 starts at the beginning (the keyframe) but frames are not displayed until t=0. output.mp4的解码从开头(关键帧)开始,但直到 t=0 时才显示帧。 In a large file, that could incur significant delay before displaying video.在大文件中,这可能会在显示视频之前产生明显的延迟。

I'm not sure how many extra frames are needed after start_pos+duration , but some will be because the end of the clip has B -frames that can reference several frames B i-directionally (backwards and forwards).我不确定在start_pos+duration之后需要多少额外的帧,但有些是因为剪辑的末尾有B帧,可以在 i 方向(向后和向前)引用多个帧B

Alas, my unsatisfying solution for this problem is to lossless re-encode the input.mp4 (adding in more keyframes), trim out my desired clips, and archive the outputs. las,我对这个问题的不满意解决方案是对input.mp4进行无损重新编码(添加更多关键帧),修剪我想要的剪辑,然后存档输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM