Используйте ffmpeg copy codec для объединения файлов * .ts в один mp4

47

У меня есть куча сегментов ts, описанных одним файлом index.m3u8:

index.m3u8        
segment1_0_av.ts  
segment2_0_av.ts  
segment3_0_av.ts  
segment4_0_av.ts  
segment5_0_av.ts

Я знаю, что все они закодированы одинаково. ffprobe дает мне следующее:

Input #0, mpegts, from 'segment1_0_av.ts':
  Duration: 00:00:10.00, start: 0.100511, bitrate: 1251 kb/s
  Program 1 
    Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p, 960x540 [SAR 1:1 DAR 16:9], 12.50 fps, 25 tbr, 90k tbn, 25 tbc
    Stream #0:1[0x101]: Audio: aac ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 105 kb/s
    Stream #0:2[0x102]: Unknown: none ([21][0][0][0] / 0x0015)

Я хотел бы объединить их в один контейнер mp4. Но когда я пытаюсь команды как:

ffmpeg -f concat -i filelist.txt -c copy output.mp4

при создании файла filelist.txt из файла index.m3u8 он жалуется на невозможность чтения различных файлов. Но преобразование файлов TS само по себе, кажется, работает нормально. Я думаю, что я не использую ffmpeg должным образом.

Как использовать ffmpeg для объединения файлов ts, описанных index.m3u8, в один контейнер mp4 с использованием кодека копирования?

изречений
источник

Ответы:

58

Я не уверен, почему ffmpeg выдает ошибку. Однако ts является одним из немногих форматов, которые можно просто объединить. Затем, как только у вас есть один ts, преобразовать в mp4.

Под окнами:

copy /b segment1_0_av.ts+segment2_0_av.ts+segment3_0_av.ts all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

Под GNU / Linux, используя bash:

cat segment1_0_av.ts segment2_0_av.ts segment3_0_av.ts > all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4
szatmary
источник
12
Вам также может понадобиться -bsf:a aac_adtstoasc.
Камило Мартин
1
Интересно отметить, что команда НЕ ffmpeg copy ..., она copy ...(под Windows)
Рон Ройстон,
26

Использование copy или cat для объединения файлов, как в случае с текущим верхним ответом szatmary, может привести к тому, что у вас будет файл, который проигрывает далеко за пределом и не может искать вместе с проблемами воспроизведения.

Вместо этого, чтобы правильно объединить эти файлы, используйте ffmpeg, как указано в https://trac.ffmpeg.org/wiki/Concatenate . (Установите ffmpeg здесь, если у вас его еще нет https://github.com/adaptlearning/adapt_authoring/wiki/Install-FFmpeg .)

Если вам лень читать мою первую ссылку, вам, в основном, нужно создать файл .txt, в котором перечислены все файлы, которые вы хотите объединить, как это делается (что моя первая ссылка дает инструкции о том, как это легко сделать) в папке, где вы ' повторное объединение:

file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

Вот копия вставки из моей первой ссылки об одном способе создания текстового файла, если у вас, например, в командной строке Windows, но, очевидно, вы можете создать файл вручную или по своему усмотрению:

(for %i in (*.ts) do @echo file '%i') > mylist.txt

Дважды проверьте, что ваш .txt файл выглядит хорошо и правильно отформатирован!

После этого в командной строке выполните:

ffmpeg -f concat -i mylist.txt -c copy all.ts

где «mylist.txt» - это только что созданный файл .txt.

Проверьте, правильно ли воспроизводится результирующий файл. Отсюда вы можете преобразовать в mp4 как обычно, если хотите:

ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4
Хуан Акино
источник
Это for %i in (*.ts) doне сортирует правильно для i> = 10. Кроме того, все работает, спасибо. Действительно, были проблемы с конкатенированным файлом, не говоря уже о том, что файл, созданный с использованием вашего метода, оказался на 16% меньше (у меня было 1400 частей на 400 КБ).
пользователь
@ Пользователь для чисел в порядке, вы можете перебирать номера, какfor i in {1..10}; do echo file \'$i.ts\' >> list.txt ; done
QWR
8

Ответ 2017

Но когда я пытаюсь использовать команды вроде ..., он жалуется на то, что не может читать различные файлы.

Когда я выполняю ffmpeg -i some.ts -c copy some.mp4на определенном видео, я получаю это сообщение об ошибке:

Malformed AAC bitstream detected: use the audio bitstream filter 
'aac_adtstoasc' to fix it ('-bsf:a aac_adtstoasc' option with ffmpeg)

av_interleaved_write_frame(): Operation not permitted

Не удивительно, что выполнение ffmpeg -i some.ts -c copy -bsf:a aac_adtstoasc some.mp4исправляет это.

7vujy0f0hy
источник
3
Получите достаточно новый, ffmpegи теперь он будет делать это автоматически.
Llogan
7

Собираем все вместе

Используя ответ Хуана Акино (и исправляя первую команду, чтобы она была совместима с Bash, и используя естественное упорядочение файлов), плюс ответ 7vujy0f0hy, простой рабочий сценарий для оболочки Linux Bash:

#!/bin/bash
for i in `ls *.ts | sort -V`; do echo "file $i"; done >> mylist.txt
ffmpeg -f concat -i mylist.txt -c copy -bsf:a aac_adtstoasc video.mp4
Франческо Галгани
источник
4

Правильный способ объединения нескольких видеофайлов из списка воспроизведения m3u8:

ffmpeg -i "index.m3u8" -codec copy output.mp4


  • плейлист m3u8 может быть в сети или локально в каталоге
    • он содержит список путей к файлам относительно списка воспроизведения
  • -codec copy чтобы избежать кодирования
  • Тип контейнера имеет значение:
    • *.mp4 хорошо, но кажется немного медленным, когда плейлист выбирается из сети
    • *.mkvили *.tsработал лучше для меня
Властимил Овчачик
источник
2

Вы можете сделать объединение просто так (с помощью bash):

for f in ./{0..<number>}.ts; do cat $f >> out.ts; done

Заменить <number>на наибольшее число (очевидно). Варианты с ffmpeg не работали должным образом. Выходной видеофайл будет странно заикаться.

Я использую цикл for, чтобы обеспечить правильный порядок файлов. Может быть, вам это не нужно. Может быть, даже возможно передать вывод в ffmpeg и преобразовать его в mp4 на лету.

Ragnarsson
источник
0

Все популярные ответы на этот вопрос, которые вводят читателей в заблуждение относительно объединения файлов TS перед запуском ffmpeg, неверны. Чтобы гарантировать, что аудио и видео не будут не синхронизированы во время сборки потока mp4, следует использовать плохо документированную, но важную функцию -f concat в ffmpeg.

    delimiterBeforeFileNumber="-"
    ls |egrep '[.]ts$' \
        |sort "-t$delimiterBeforeFileNumber" -k2,2n \
        |sed -r "s/(.*)/file '\1'/" >ts.files.txt

    ffmpeg -f concat -i ts.files.txt -c copy tsw.014.ts.mp4

Две подготовительные строки кода просто создают файл, содержащий список файлов TS в этом формате строки:

    file 'seg-37-a.ts'
Дуглас Дасеко
источник
На самом деле, когда я попробовал это, между сегментами в финальном видео было небольшое «заикание». Так что, по крайней мере, в этом случае это помогло объединить файлы TS в первую очередь.
Sphinxxx