在视频播放器中立即知道总视频时长 (ffmpeg / html)

Make total video duration instantly known in video player (ffmpeg / html)

TL;DR

阻止视频 'lazy' 加载视频总时长的正确 ffmpeg 设置是什么?

问题

我正在尝试使用 ffmpeg(在 NodeJS 中)对视频进行转码。 转码完成后,ffmpeg 会自动将视频上传到存储桶 (GCP)。

然而,ffmpeg 生成的视频在 HTML 视频播放器中播放时没有明确的总持续时间。仅在 x(毫秒)秒后才知道并显示总视频持续时间。

代码

使用 fluent-ffmpeg NodeJS 库:

const settings: VideoHDPresetSettings = {
  format: "mp4",
  codec: "libx264",
  size: "1920x1080",
  ratio: "16:9",
  options: [
    "-movflags", "frag_keyframe+empty_moov+faststart",
    "-preset", "veryfast",
    "-crf", "16",
  ],
};

ffmpeg({source: "input.mp4"})
 .format(settings.format)
 .videoCodec(settings.codec)
 .size(settings.size)
 .aspectRatio(settings.ratio)
 .outputOptions(settings.options)
 .writeToStream(outputStream);

这是 fluent-ffmpeg 生成的命令:

ffmpeg -i input.mp4 -vcodec libx264 -filter:v scale=w=1920:h=1080 -f mp4 -movflags frag_keyframe+empty_moov+faststart -preset veryfast -crf 16 pipe:1

例子

原创

这就是我想要的,当视频加载时,总视频时长立即已知。

https://storage.googleapis.com/uhasselt/problem/original(已过期)

Ffmpeg:

这是上面的代码生成的,当加载视频时,总视频持续时间是已知的。 很难检测到此视频,因此请在时间轴上查看视频的总时长时刷新几次。

https://storage.googleapis.com/uhasselt/problem/ffmpeg-result(已过期)

问题

阻止视频 'lazy' 加载视频总时长的正确 ffmpeg 设置是什么?我做错了什么?

经过一些额外的测试后,我发现 .writeToStream(...) 导致了这种行为。这种保存技术用于将结果直接流式传输到某些 url,而无需将其保存在机器的本地磁盘上。

我现在使用 .save("./output/path.mp4") 函数首先将 ffmpeg 的结果保存在磁盘上,然后将其流式传输到我的存储桶(不包含在下面的代码中)。

我不确定为什么会这样...我认为这与 ffmpeg 现在能够在交付最终视频之前跳回并更改以前保存的元数据有关(这是不可能的.writeToStream(...) 因为数据流是一个连续的数据流,无法跳回)。

如果您使用的是 CLI ffmpeg 版本而不是 fluent-ffmpeg,则此更改对应于在您的 ffmpeg 末尾不使用 pipe:1命令。

这是最终的解决方案

// Exactly the same
const settings: VideoHDPresetSettings = {
  format: "mp4",
  codec: "libvpx-vp9",
  size: "1920x1080",
  ratio: "16:9",
  options: [
    "-movflags", "frag_keyframe+empty_moov+faststart",
    "-preset", "veryfast",
    "-crf", "30",
  ],
};

ffmpeg({source: "input.mp4"})
  .format(settings.format)
  .videoCodec(settings.codec)
  .size(settings.size)
  .aspectRatio(settings.ratio)
  .outputOptions(settings.options)
  .save("./output.mp4"); // NEW!