如何混合 MKV 和 MKA 文件并使其在浏览器中播放?

How can I mux a MKV and MKA file and get it to play in a browser?

我正在使用 ffmpeg 将 .mkv 和 .mka 文件合并到 .mp4 文件中。我当前的命令如下所示:

ffmpeg -i video.mkv -i audio.mka output_path.mp4

音频和视频文件是来自 Amazon S3 的预签名 url。即使在资源充足的服务器上,这个过程也非常缓慢。我已经研究过可以告诉 ffmpeg 跳过重新编码每一帧的情况,但我认为在我的情况下它实际上确实需要重新编码每一帧。

我已经将 2 个示例文件下载到我的 macbook pro 并通过自制软件在本地安装了 ffmpeg。当我 运行 命令

ffmpeg -i video.mkv -i audio.mka -c copy output.mp4

我得到以下输出:

ffmpeg version 3.3.2 Copyright (c) 2000-2017 the FFmpeg developers
  built with Apple LLVM version 8.1.0 (clang-802.0.42)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.3.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-libmp3lame --enable-libx264 --enable-libxvid --enable-opencl --disable-lzma --enable-vda
  libavutil      55. 58.100 / 55. 58.100
  libavcodec     57. 89.100 / 57. 89.100
  libavformat    57. 71.100 / 57. 71.100
  libavdevice    57.  6.100 / 57.  6.100
  libavfilter     6. 82.100 /  6. 82.100
  libavresample   3.  5.  0 /  3.  5.  0
  libswscale      4.  6.100 /  4.  6.100
  libswresample   2.  7.100 /  2.  7.100
  libpostproc    54.  5.100 / 54.  5.100
Input #0, matroska,webm, from '319_audio_1498590673766.mka':
  Metadata:
    encoder         : GStreamer matroskamux version 1.8.1.1
    creation_time   : 2017-06-27T19:10:58.000000Z
  Duration: 00:00:03.53, start: 2.831000, bitrate: 50 kb/s
    Stream #0:0(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    Metadata:
      title           : Audio
Input #1, matroska,webm, from '319_video_1498590673766.mkv':
  Metadata:
    encoder         : GStreamer matroskamux version 1.8.1.1
    creation_time   : 2017-06-27T19:10:58.000000Z
  Duration: 00:00:03.97, start: 2.851000, bitrate: 224 kb/s
    Stream #1:0(eng): Video: vp8, yuv420p(progressive), 640x480, SAR 1:1 DAR 4:3, 30 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      title           : Video
[mp4 @ 0x7fa4f0806800] Could not find tag for codec vp8 in stream #0, codec not currently supported in container
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
  Stream #1:0 -> #0:0 (copy)
  Stream #0:0 -> #0:1 (copy)
    Last message repeated 1 times

看来我正在使用的特定编码是 vp8 视频和 opus 音频文件,我认为它们与 .mp4 输出容器不兼容。我将不胜感激涵盖将 vp8 和 opus 最佳地合并到 .mp4 输出的方法的答案,或者将我指向与 vp8 和 opus 兼容并且可在网络和移动设备上播放以便我可以绕过的输出媒体格式方向的答案完全重新编码步骤。

编辑:

只是想在遵循 LordNeckbeard 的建议后提供一个基准:

4 min 41 second video transcoded locally on my mac

LordNeckbeard’s approach : 15 mins 55 seconds (955 seconds)
Current approach : 18 mins 49 seconds (1129 seconds)

18% speed increase

您可以使用 ffmpeg 复用 and/or 将 MKV 和 MKA 重新编码为 Web 浏览器兼容的格式,例如 Webm 或 MP4。

Webm mux:如果输入格式是 VP8/VP9 带有 Vorbis 或 Opus 音频的视频

如果您的输入是 VP8 或 VP9 视频和 Vorbis 或 Opus 音频,例如您问题中的输入,您可以只混合到 Webm 中。这应该很快,因为它不会重新编码:

ffmpeg -i video.mkv -i audio.mka -c copy output.webm

默认 stream selection 行为是 select 每种流类型一个流,因此使用 -map 您可以告诉它选择哪些流以防止错误。例如,如果两个输入都包含多个流,但您只希望第一个视频流来自 video.mkv,第一个音频流来自 audio.mka

ffmpeg -i video.mkv -i audio.mka -map 0:v:0 -map 1:a:0 -c copy -movflags +faststart output.webm

MP4 mux:如果输入格式为 H.264/H.265 视频和 AAC 音频

ffmpeg -i video.mkv -i audio.mka -c copy -movflags +faststart output.mp4
    添加
  • -movflags +faststart 是因为您提到了网络播放。这将允许视频在客户端完全下载之前开始播放。

Webm 重新编码:如果输入格式与 Webm 不兼容

您需要重新编码:

ffmpeg -i video.mkv -i audio.mka -c:v libvpx-vp9 -crf 33 -b:v 0 -c:a libopus output.webm
  • VP9 真的很慢。如果您想要 VP8,请改用 -c:v libvpx。有关详细信息,请参阅 FFmpeg Wiki: VP8 and FFmpeg Wiki: VP9.

  • 如果您没有 libopus 支持,请改用 libvorbis。

MP4 重新编码:如果输入格式与 MP4 不兼容

ffmpeg -i video.mkv -i audio.mka -c:v libx264 -crf 23 -preset medium -c:a aac -movflags +faststart output.mp4
  • 对于视频,用-crf控制质量,用-preset控制编码速度。有关详细信息,请参阅 FFmpeg Wiki: H.264 and FFmpeg Wiki: AAC

  • 如果您的目标设备在其支持的 H.264 配置文件中受到限制,您可以添加 -profile:v main-profile:v baseline.

ffprobe 用于脚本

您可以编写一个脚本来自动执行此操作。 ffprobe可用于判断格式:

$ ffprobe -loglevel error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 video.mkv
h264
$ ffprobe -loglevel error -select_streams a:0 -show_entries stream=codec_name -of csv=p=0 audio.mka 
aac

ffprobe 输出可用作 if/then 语句中的变量。