ffprobe/ffmpeg 字幕索引不匹配

ffprobe/ffmpeg 字幕索引不匹配

这让我发疯了。

我有一个视频文件,input.mkv其中包含多个字幕流。我想将其中一个字幕流硬编码到新文件中。我通常这样做:

inputfile="input.mkv"
outputfile="out.mp4"
ffmpeg -i "$inputfile" -vf "subtitles=$(printf "%q" "$inputfile")" "$outputfile"

现在由于input.mkv有多个子流,我需要指定我想要哪一个。输入ffprobe

(为了便于阅读,我将删除一些不相关的(我认为)字段)

$ ffprobe -v quiet -print_format json -show_streams -select_streams s input.mkv | jq -r '.streams | .[]'
{
  "index": 2,
...cut...
  },
  "tags": {
    "language": "zh-Hans",
    "title": "中文(简体)",
    "DURATION": "00:23:40.083000000"
  }
}
{
  "index": 3,
...cut...
  },
  "tags": {
    "language": "zh-Hant",
    "title": "中文(繁體)| 繁化姬",
    "DURATION": "00:23:40.083000000"
  }
}
{
  "index": 4,
...cut...
  },
  "tags": {
    "language": "en",
    "title": "English",
    "DURATION": "00:23:40.083000000"
  }
}
{
  "index": 5,
...cut...
  },
  "tags": {
    "language": "th",
    "title": "ภาษาไทย",
    "DURATION": "00:23:40.079000000"
  }
}
{
  "index": 6,
...cut...
  },
  "tags": {
    "language": "vi",
    "title": "Tiếng Việt",
    "DURATION": "00:23:40.039000000"
  }
}
{
  "index": 7,
...cut...
  },
  "tags": {
    "language": "id",
    "title": "Bahasa Indonesia",
    "DURATION": "00:23:40.079000000"
  }
}
{
  "index": 8,
...cut...
  },
  "tags": {
    "language": "ms",
    "title": "Bahasa Melayu",
    "DURATION": "00:23:40.080000000"
  }
}

现在我想要英文子流,所以我认为我需要子流 4:

$ ffmpeg -i "$inputfile" -to 00:00:10 -vf "subtitles=$(printf "%q" "$inputfile"):si=4" out.mp4

但是,这给我带来了一种我无法阅读(或识别)的子语言。尝试了不同的索引后,索引 2 让我得到了英语流:

$ ffmpeg -i "$inputfile" -to 00:00:10 -vf "subtitles=$(printf "%q" "$inputfile"):si=2" out.mp4

我想在脚本中完成所有这些操作,并使用 ffprobe 中的索引来获取正确的流:

$ ffprobe -v quiet -print_format json -show_streams -select_streams s "$inputfile" | jq -r '.streams | .[] | select(.tags.language=="en") | .index'
4

为什么它们不匹配?有没有更好的方法来获取正确的索引?可能总是少 2 个吗?

任何帮助将不胜感激。

//ffmpeg版本信息:

$ ffmpeg -version
ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil      56. 31.100 / 56. 31.100
libavcodec     58. 54.100 / 58. 54.100
libavformat    58. 29.100 / 58. 29.100
libavdevice    58.  8.100 / 58.  8.100
libavfilter     7. 57.100 /  7. 57.100
libavresample   4.  0.  0 /  4.  0.  0
libswscale      5.  5.100 /  5.  5.100
libswresample   3.  5.100 /  3.  5.100
libpostproc    55.  5.100 / 55.  5.100

答案1

您的英文字幕流是:

  • 文件的第 5 个流(因此索引为 4)(绝对位置)
  • 文件中的第三个字幕流(因此索引为 2)(相对位置)

因此存在歧义...subtitles过滤器需要相对位置。分两步可以更简单:

ffmpeg -i "$inputfile" -map 0:s:language:en -c copy sub.mkv
ffmpeg -i "$inputfile" -vf "subtitles=sub.mkv" "$outputfile"

第一个 ffmpeg 只会保留英文字幕流并将其放入sub.mkv。然后第二个不必关心索引。

相关内容