Обрезать аудиопоток до длины видеопотока

У меня есть файл mp4 (преобразованный из файла mkv), в котором звук длиннее, чем видеопоток. Этот файл плохо воспроизводится в моем приложении для потоковой передачи мультимедиа (или MPC-HC), когда я достигаю конца файла.

Пример вывода из mp4info:

File:
  major brand:      mp42
  minor version:    200
  compatible brand: isom
  compatible brand: iso2
  compatible brand: avc1
  compatible brand: mp41
  fast start:       yes

Movie:
  duration:   1553152 ms
  time scale: 1000
  fragments:  no

Found 3 Tracks
Track 1:
  flags:        3 ENABLED IN-MOVIE
  id:           1
  type:         Video
  duration: 1524398 ms
  language: und
  media:
    sample count: 36549
    timescale:    90000
    duration:     137195807 (media timescale units)
    duration:     1524398 (ms)
    bitrate (computed): 8508.739 Kbps
  display width:  1444.000000
  display height: 1080.000000
  frame rate (computed): 23.976
  Sample Description 0
    Coding:      avc1 (H.264)
    Width:       1444
    Height:      1080
    Depth:       24
    AVC Profile:          77 (Main)
    AVC Profile Compat:   40
    AVC Level:            40
    AVC NALU Length Size: 4
    AVC SPS: [674d4028eca02d8113cf2e02d404040500000300010002bf200f183196]
    AVC PPS: [68cb8132c8]
    Codecs String: avc1.4D4028
Track 2:
  flags:        3 ENABLED IN-MOVIE
  id:           2
  type:         Audio
  duration: 1553152 ms
  language: eng
  media:
    sample count: 72804
    timescale:    48000
    duration:     74551296 (media timescale units)
    duration:     1553152 (ms)
    bitrate (computed): 125.679 Kbps
  Sample Description 0
    Coding:      mp4a (MPEG-4 Audio)
    Stream Type: Audio
    Object Type: MPEG-4 Audio
    Max Bitrate: 125678
    Avg Bitrate: 125678
    Buffer Size: 0
    Codecs String: mp4a.40.2
    MPEG-4 Audio Object Type: 2 (AAC Low Complexity)
    MPEG-4 Audio Decoder Config:
      Sampling Frequency: 48000
      Channels: 1
      Extension:
        Object Type: Spectral Band Replication
        SBR Present: no
        PS Present:  no
        Sampling Frequency: 0
    Sample Rate: 48000
    Sample Size: 16
    Channels:    2
Track 3:
  flags:        2 IN-MOVIE
  id:           3
  type:         Text
  duration: 1524356 ms
  language: ```
  media:
    sample count: 5
    timescale:    1000
    duration:     1524356 (media timescale units)
    duration:     1524356 (ms)
    bitrate (computed): 0.001 Kbps
  Sample Description 0
    Coding:      text

В частности, продолжительность «Фильма» составляет 1553152 мс (25:53,152), что слишком долго. Продолжительность видеопотока составляет 1524398 мс (25:24,398), что соответствует действительности. Продолжительность аудиопотока составляет 1553152 мс (25:53,152) и, похоже, определяет продолжительность «Фильма».

Я хочу установить продолжительность «Фильма» на значение продолжительности видео без повторного кодирования . Кажется, что это было бы легко сделать, но я не могу найти никакого решения.

Я пробовал:

  • ffmpeg -i file.mp4 -shortest -codec copy out.mp4- не имеет никакого эффекта (кроме удаления быстрого запуска mp4, который я хочу сохранить).
  • mp4box -add file.mp4 -new out.mp4- также не фиксирует продолжительность.
  • Ремуксирование оригинального файла mkv с помощью MkvToolnix.

ffmpegс -tопцией может работать, но мне нужно просмотреть несколько тысяч файлов, и я не хочу вручную вводить разные команды для каждого из них.


Подробнее:

У меня есть несколько дисков BluRay, которые я скопировал пару лет назад с помощью MakeMKV 1.10.4. С самими файлами MKV та же проблема: продолжительность сегмента составляет 25:53.088, с тегом DURATION фильма дорожки 1 25:24.397875. Тег DURATION фильма дорожки 2 (аудио) равен 25:53.14133333. Повторное копирование дисков BluRay является приемлемым решением, если эта проблема устранена (я не вытаскивал диски BluRay из хранилища и не пробовал).

Я преобразовал эти файлы MakeMKV mkv с помощью HandBrake в файлы mkv h265. Эти файлы также имеют несоответствие длительности сегмента тегу DURATION фильма.

При воспроизведении файлов MKV мое приложение для потоковой передачи мультимедиа (и MPC-HC) правильно определяет длину файла из тега фильма DURATION. Там нет проблем, хотя продолжительность файла mkv неверна.

Что я хочу сделать, так это включить несколько старых плееров, закодировав их в h264 mp4 с помощью faststart. Я полагаю, что мое приложение для потоковой передачи мультимедиа сможет обслуживать файлы напрямую, вместо перекодирования в h264 или повторного мультиплексирования (в зависимости от клиента, оно всегда делает одно или другое прямо сейчас).

У меня настроен HandBrake с моими новыми настройками h264/mp4, и я хотел бы продолжить использовать это приложение для перекодирования исходных файлов MakeMKV.

Идеальным решением было бы исправить длительность сегмента mkv в исходных файлах MakeMKV. Исправление файлов mp4 постфактум также было бы приемлемо, но в этот момент я не хочу перекодировать.

Версии актуальны для всего, кроме MakeMkv, так как я скопировал их пару лет назад:

ffmpeg 4.1.4
mp4info 1.3.4 (Bento4 1.5.1.0)
MKVToolNix 35.0.0
MP4Box 0.8.0-rev47-gbafe4cd3-master
MakeMKV 1.10.4

Ответы (1)

Следует использовать библиотечный флаг avformat, чтобы остановить мультиплексирование с самым коротким потоком.

ffmpeg -i file.mp4 -map 0 -c copy -fflags +shortest -max_interleave_delta 1G -movflags +faststart out.mp4
В итоге это привело к частичному усечению файла mp4. Я не уверен, что происходит. Тем не менее, этот подход сработал для исправления файла mkv, поэтому у меня есть правильный источник для кодирования моего файла mp4. Большое спасибо! Окончательная командная строка:ffmpeg -i file.mkv -map 0 -c copy -fflags +shortest -max_interleave_delta 0 out.mkv
@StephenCleary: Раздражает, что shortestлогика также применима к дорожкам субтитров, которые обычно короче, чем видео и аудио :( Мне пришлось удалить субтитры в первоначальном ремультиплексировании сокращения: , а затем ffmpeg -i original.mkv -c copy -sn -fflags +shortest -max_interleave_delta 0 trimmed-no-subs.mkvвклеить субтитры обратно:ffmpeg -i trimmed-no-subs.mkv -i original.mkv -map 0 -map 1:s -c copy trimmed.mkv