Sử dụng codec sao chép ffmpeg để kết hợp các tệp * .ts thành một mp4 duy nhất


47

Tôi đã có một loạt các phân đoạn ts được mô tả bởi một tệp index.m3u8:

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

Tôi biết tất cả chúng đều được mã hóa theo cùng một cách. ffprobe cho tôi những điều sau:

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)

Tôi muốn kết hợp chúng vào một thùng chứa mp4. Nhưng khi tôi thử các lệnh như:

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

trong đó việc tạo filelist.txt từ tệp index.m3u8, nó phàn nàn về việc không thể đọc các tệp khác nhau. Nhưng bản thân việc chuyển đổi các tập tin ts dường như hoạt động tốt. Tôi nghĩ rằng tôi không sử dụng ffmpeg đúng cách.

Làm cách nào để sử dụng ffmpeg để kết hợp các tệp ts được mô tả bởi index.m3u8 vào một thùng chứa mp4 bằng cách sử dụng codec sao chép?

Câu trả lời:


58

Tôi không chắc tại sao ffmpeg lại báo lỗi cho bạn. Tuy nhiên ts là một trong số ít các định dạng có thể được nối đơn giản. Sau đó, khi bạn có một ts duy nhất, truyền sang mp4.

Dưới cửa sổ:

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

Trong GNU / Linux, sử dụng 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

12
Bạn cũng có thể cần -bsf:a aac_adtstoasc.
Camilo Martin

1
ffmpeg copy ...Thật thú vị khi lưu ý rằng lệnh KHÔNG , đó là copy ...(trong Windows)
Ron Royston

25

Sử dụng bản sao hoặc con mèo để kết hợp các tệp như câu trả lời hàng đầu hiện tại của szatmary có thể khiến bạn có một tệp vượt quá giới hạn và không thể tìm kiếm cùng với các vấn đề phát lại.

Thay vào đó, để kết hợp các tệp này đúng cách, hãy sử dụng ffmpeg theo hướng dẫn trong https://trac.ffmpeg.org/wiki/Concatenate . (Cài đặt ffmpeg tại đây nếu bạn chưa có https://github.com/adaptlearning/adapt_ournaling/wiki/Installing-FFmpeg .)

Nếu bạn quá lười để đọc liên kết đầu tiên của tôi, về cơ bản bạn phải tạo tệp .txt liệt kê tất cả các tệp bạn muốn kết hợp như vậy (liên kết đầu tiên của tôi cung cấp hướng dẫn về cách thực hiện dễ dàng) trong thư mục nơi bạn ' đang thực hiện việc nối lại:

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

Đây là một bản sao dán từ liên kết đầu tiên của tôi trên một cách để tạo tệp văn bản nếu bạn có Windows trên dòng lệnh chẳng hạn nhưng rõ ràng bạn có thể tạo tệp theo cách thủ công hoặc theo cách bạn muốn:

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

Kiểm tra kỹ xem tệp .txt của bạn có tốt không và được định dạng chính xác!

Sau này, trên dòng lệnh chạy:

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

trong đó 'mylist.txt' là tệp .txt bạn vừa tạo.

Kiểm tra xem tập tin kết quả phát video chính xác. Từ đây, bạn có thể truyền sang mp4 như bình thường nếu bạn muốn:

ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

Điều đó for %i in (*.ts) dokhông sắp xếp chính xác cho i> = 10. Ngoài ra, mọi thứ đều hoạt động, cảm ơn. Thật vậy, có vấn đề với tệp được nối, chưa kể rằng tệp được tạo bằng phương pháp của bạn hóa ra nhỏ hơn 16% (tôi có 1400 phần 400kb).
người dùng

@user cho các số theo thứ tự bạn có thể lặp qua các số nhưfor i in {1..10}; do echo file \'$i.ts\' >> list.txt ; done
qwr

8

Câu trả lời năm 2017

Nhưng khi tôi thử các lệnh như thế ..., nó phàn nàn về việc không thể đọc các tệp khác nhau.

Khi tôi thực hiện ffmpeg -i some.ts -c copy some.mp4trên một video nhất định, tôi nhận được thông báo lỗi này:

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

Không ngạc nhiên, thực hiện ffmpeg -i some.ts -c copy -bsf:a aac_adtstoasc some.mp4sửa chữa nó.


3
Nhận một đủ mới ffmpegvà bây giờ nó sẽ làm điều này tự động.
llogan

7

Đặt tất cả lại với nhau

Sử dụng câu trả lời của Juan Aquino (và sửa lệnh đầu tiên để tương thích với Bash và sử dụng thứ tự tự nhiên của các tệp), cộng với câu trả lời của 7vujy0f0hy, một kịch bản làm việc đơn giản cho trình bao Linux Bash là:

#!/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

Cách chính xác để ghép nhiều tệp video từ danh sách phát m3u8 là

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


  • danh sách phát m3u8 có thể trên web hoặc cục bộ trong thư mục
    • nó chứa danh sách các đường dẫn tệp liên quan đến danh sách phát
  • -codec copy để tránh mã hóa
  • vấn đề loại container:
    • *.mp4 vẫn ổn nhưng có vẻ hơi chậm khi mux khi danh sách phát được tải từ web
    • *.mkvhoặc *.tslàm việc tốt nhất cho tôi

2

Bạn có thể thực hiện cách ghép đơn giản như vậy (với bash):

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

Thay thế <number>bằng số cao nhất (rõ ràng). Các biến thể với ffmpeg không hoạt động đúng. Các tập tin video đầu ra sẽ nói lắp một cách kỳ lạ.

Tôi sử dụng vòng lặp for để đảm bảo thứ tự chính xác của các tập tin. Có lẽ bạn không cần nó. Có lẽ thậm chí có thể chuyển đầu ra thành ffmpeg và chuyển đổi nó thành mp4 khi đang di chuyển.


1

Bạn có thể sử dụng ống các tệp ts này vào ffmpeg và xuất tệp mp4.

cat *.ts | ffmpeg -i pipe: -c:a copy -c:v copy output.mp4

hoặc Nếu bạn tên tệp ts không có thứ tự,

grep .*.ts index.m3u8 | xargs cat | ffmpeg -i pipe: -c:a copy -c:v copy output.mp4


0

Tất cả các câu trả lời phổ biến cho câu hỏi này khiến người đọc đánh lừa để nối các tệp TS trước khi chạy ffmpeg là không chính xác. Để đảm bảo âm thanh và video không bị mất đồng bộ trong quá trình lắp ráp luồng mp4, nên sử dụng tính năng "-f concat" được ghi chép kém nhưng quan trọng của 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

Hai dòng mã chuẩn bị chỉ tạo một tệp chứa danh sách các tệp TS ở định dạng dòng này:

    file 'seg-37-a.ts'

Trên thực tế, khi tôi thử điều này, có một chút "nói lắp" giữa các phân đoạn trong video cuối cùng. Vì vậy, ít nhất trong trường hợp đó, nó đã giúp ghép các tệp TS trước.
Nhân sư
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.