Câu hỏi Làm thế nào để nối hai tập tin MP4 bằng cách sử dụng FFmpeg?


Tôi đang cố gắng để nối hai tập tin mp4 bằng cách sử dụng ffmpeg. Tôi cần đây là một quá trình tự động vì thế tại sao tôi chọn ffmpeg. Tôi đang chuyển đổi hai tập tin vào tập tin .ts và sau đó ghép chúng và sau đó cố gắng để mã hóa tập tin .ts concated. Các tập tin là h264 và aac được mã hóa và tôi hy vọng giữ chất lượng giống hoặc gần với bản gốc nhất có thể.

ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

Thật không may tôi nhận được thông báo lỗi sau đây trở lại từ ffmpeg trong quá trình mã hóa:

[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s    
av_interleaved_write_frame(): Error while opening file

Điều này xảy ra khoảng một nửa thông qua mã hóa mà làm cho tôi nghĩ rằng bạn không thể concat hai .ts tập tin với nhau và có nó làm việc.


181
2017-09-07 11:40


gốc


Như minh họa trong câu trả lời của tôi, dưới đây, chuyển mã các tập tin là không cần thiết. FFmpeg có thể nối nhiều tập tin mp4 vào một tập tin mp4 duy nhất, mà không cần bất kỳ bước trung gian nào và không cần phải mã hóa lại. Và không có phần mềm ngoại trừ ffmpeg là cần thiết. Các trường hợp duy nhất trong đó mã hóa lại sẽ được yêu cầu là nếu các tập tin ban đầu không phải là tập tin mp4 nhưng mục đích là để tạo ra một tập tin mp4 như tập tin đầu ra. Xem câu trả lời của tôi bên dưới để biết chi tiết. - Ed999


Các câu trả lời:


FFmpeg có ba phương pháp ghép nối.

1. bộ lọc video concat

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
  -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \
  -map "[v]" -map "[a]" output.mkv

Lưu ý rằng phương thức này thực hiện mã hóa lại.

2. concat demat

$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

$ ffmpeg -f concat -i mylist.txt -c copy output

cho cửa sổ:

(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

3. giao thức concat

ffmpeg -i "concat:input1|input2" -codec copy output

Phương pháp này không hoạt động đối với nhiều định dạng, bao gồm cả MP4, do tính chất của các định dạng này và kết nối đơn giản được thực hiện theo phương pháp này.

Cái nào để sử dụng

  • bộ lọc concat: Sử dụng nếu đầu vào của bạn không có cùng thông số (chiều rộng, chiều cao, v.v.) hoặc không cùng định dạng / codec hoặc nếu bạn muốn thực hiện bất kỳ tính năng lọc nào. (Bạn có thể mã hóa lại chỉ các đầu vào không khớp với nhau để chúng chia sẻ cùng một codec và các thông số khác, sau đó sử dụng trình giảm tốc concat để tránh mã hóa lại các đầu vào khác).

  • concat demat: Sử dụng khi bạn muốn tránh mã hóa lại và định dạng của bạn không hỗ trợ ghép nối cấp tệp (hầu hết các tệp được người dùng chung sử dụng không hỗ trợ nối cấp tệp).

  • giao thức concat: Sử dụng với các định dạng hỗ trợ nối cấp tập tin (MPEG-1, MPEG-2 PS, DV). Không sử dụng với MP4.

Nếu nghi ngờ hãy thử các demuxer concat.

Cũng thấy


390
2018-06-24 07:47



Ký tự thoát dấu nhắc lệnh Windows là ^; Tôi cũng chạy vào các vấn đề với các dấu ngoặc kép để nó trở thành: ffmpeg -i concat: input1 ^ | input2 -codec đầu ra bản sao - user423430
thnx. "concat demuxer" làm việc cho "mp4". - Bhaskar Dabhi
Để sử dụng trực tuyến: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv chấp nhận nhiều codec hơn mp4, nhưng bạn cũng có thể thử với mp4). Các -safe 0 dành cho các phiên bản ffmpeg gần đây đang phàn nàn về Tên tệp không an toàn, và -type f chỉ dành cho các tệp danh sách. Tôi đã thêm | sort để sắp xếp các tệp theo thứ tự abc; bởi vì find đọc chúng theo thứ tự như được lưu trên hệ thống tập tin. Hoạt động cũng cho các tệp có khoảng trắng. - erik
Đối với tôi, trong Windows, các dấu ngoặc kép làm việc (thay vì dấu ngoặc đơn trong ví dụ của bạn): ffmpeg -i "concat:input1|input2" -codec copy output. Không cần phải thoát khỏi nhân vật đường ống. - Shovalt
@erik đã đề cập đến số an toàn 0, điều quan trọng nếu bạn có các mục nhập tệp như tệp 'Clip (ngày 27 tháng 2 năm 2017 lúc 859 sáng) .mp4' - Maxim Veksler


Đây là một cách nhanh chóng (mất chưa tới 1 phút) và mất dữ liệu để thực hiện điều này mà không cần các tệp trung gian: -

ls Movie_Part_1.mp4 Movie_Part_2.mp4 | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4

"Ls" chứa các tệp để tham gia Các "perl" tạo ra các tập tin nối vào-the-fly vào một đường ống Phần "-i -" cho ffmpeg đọc từ đường ống

(lưu ý - các tệp của tôi không có dấu cách hoặc thứ gì lạ trong chúng - bạn sẽ cần trình thoát vỏ thích hợp nếu bạn muốn thực hiện ý tưởng này với các tệp "cứng").


36
2018-03-27 12:44



Đã làm điều này trên OSX và nó đã làm việc tuyệt vời! Tuyệt vời, giải pháp lossless nhanh với ít yêu cầu. - GM Lucid
Bạn cũng có thể làm ls * | perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4 nếu tệp của bạn được đặt tên và theo thứ tự. Làm việc tuyệt vời cho tôi trên OS X, chính xác những gì tôi muốn. - natebeaty
Trên Linux, tôi đã sử dụng tính năng này: ffmpeg -safe 0 -f concat -i <(find . -type f -name '*' -printf "file '$PWD/%p'\n" | sort) -c copy output.mkv(mkv chấp nhận nhiều codec hơn mp4, nhưng bạn cũng có thể thử với mp4). Các -safe 0 dành cho các phiên bản ffmpeg gần đây đang phàn nàn về Tên tệp không an toàn, và -type f chỉ dành cho các tệp danh sách. Tôi đã thêm | sort để sắp xếp các tệp theo thứ tự abc; bởi vì find đọc chúng theo thứ tự như được lưu trên hệ thống tập tin. Hoạt động cũng cho các tệp có khoảng trắng. - erik
Trong Windows CMD, tôi đã sử dụng nó: ls *mp4 | sed "s/\(*mp4\)/file \1/" | ffmpeg -f concat -i - -c:v copy output.mp4 - Bird
Tôi phải thêm thông số này vào ffmpeg Để làm cho nó hoạt động: -protocol_whitelist file,tcp,http,pipe - Bensge


Tôi đã kết thúc bằng cách sử dụng mpg như là định dạng trung gian và nó làm việc (Chú ý đây là một ví dụ nguy hiểm, -qscale 0 sẽ tái mã hóa video ...)

ffmpeg -i 1.mp4 -qscale 0 1.mpg
ffmpeg -i 2.mp4 -qscale 0 2.mpg
cat 1.mpg 2.mpg | ffmpeg -f mpeg -i - -qscale 0 -vcodec mpeg4 output.mp4

28
2017-09-07 11:53



Theo nhận xét này, -sameq đã xóa bỏ. Sử dụng -qscale 0 thay thế. - Xavier Ho
-sameq không có nghĩa là "cùng chất lượng" và đã bị xóa khỏi ffmpeg như đã đề cập bởi @XavierHo. - LordNeckbeard
Có vẻ như một sự xấu hổ khi phải chuyển mã video thông qua định dạng trung gian chỉ để ghép hai tệp. Bạn sẽ bị mất thế hệ. Tốt hơn là không đi sâu hơn định dạng vùng chứa và sử dụng concat lệnh trong ffmpeg, như @rogerdpack làm ở trên. - Randall Cook
Làm thế nào đến đây là một câu trả lời được chấp nhận? Đây là phương pháp rất tệ. - Sarge Borsch
@SargeBorsch Vì nó hoạt động. Tôi đã thử mọi thứ khác trên trang-- Không ai trong số họ làm việc. - Andrew


Tôi đã cố gắng nối ba .mp3 tập tin âm thanh thành một .m4a tập tin và lệnh ffmpeg này hoạt động.

Lệnh nhập:

ffmpeg -i input1.mp3 -i input2.mp3 -i input3.mp3 -filter_complex concat=n=3:v=0:a=1 -f MOV -vn -y input.m4a

Ý nghĩa của: "-filter_complex concat = n = 3: v = 0: a = 1" :
 

concat có nghĩa là sử dụng chức năng kết nối truyền thông (nối).
n có nghĩa là xác nhận tổng số tệp đầu vào.
v có nghĩa có video? sử dụng 0 = không có video, 1 = chứa video.
một có nghĩa có âm thanh? sử dụng 0 = không có âm thanh, 1 = chứa âm thanh.
-f nghĩa là định dạng tệp lực (để xem tất cả định dạng được hỗ trợ, sử dụng ffmpeg -formats)
-vn có nghĩa là tắt video (và cũng -an sẽ tắt âm thanh nếu không muốn)
-y có nghĩa là ghi đè lên các tập tin đầu ra (nếu tập tin đầu ra đã tồn tại).

Để biết thêm thông tin: sử dụng ffmpeg -h full in tất cả các tùy chọn (bao gồm tất cả các tùy chọn định dạng và codec cụ thể, rất dài)


26
2018-04-09 09:47



Tôi dùng cái này -f concat -safe 0 -i "file.txt" -c copy -y "OutPut.mp4" nó sẽ concat nhưng khi một số video được với âm thanh và một số là không có âm thanh nó không phải là làm việc như thế nào tôi có thể sắp xếp ra điều này. Cảm ơn - - Ahmad
Những công việc này. Cảm ơn bạn đã giải thích chi tiết trong câu trả lời của bạn. Nó rất hữu ích. - Joe T. Boka


cho tệp MP4:

Nếu chúng không chính xác giống nhau (100% cùng codec, cùng độ phân giải, cùng loại) tệp MP4 thì bạn phải chuyển mã chúng thành luồng trung gian lúc đầu:

ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts
ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts
// now join
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

Kết quả: Đầu ra sẽ hoạt động giống như tệp đầu tiên (và không phải tệp thứ hai)


23
2018-05-13 17:34



Như minh họa trong câu trả lời của tôi, dưới đây, chuyển mã các tập tin là không cần thiết. FFmpeg có thể nối nhiều tập tin mp4 vào một tập tin mp4 duy nhất - mà không cần bất kỳ bước trung gian nào, và không cần phải mã hóa lại. Các trường hợp duy nhất trong đó bất kỳ mã hóa lại sẽ là cần thiết là nếu các tập tin ban đầu không phải là tập tin mp4 nhưng mục đích là để tạo ra một tập tin mp4 như tập tin đầu ra. - Ed999
@ Ed999 không, trong nhiều trường hợp nó không thể trực tiếp nối .. ( - T.Todua
@T. Todua: Tôi muốn được quan tâm để tìm hiểu những gì chính xác là sự khác biệt giữa hai tập tin nguồn mp4 của bạn. Họ có sử dụng các tỷ lệ mẫu khác nhau (ví dụ: 44,100 Hz và 48.000 Hz) không? Hay họ đang sử dụng các tốc độ bit khác nhau (ví dụ: 128 kbps và 64 kbps)? Trong trường hợp như vậy, tôi không hoàn toàn hiểu làm thế nào lệnh-copy (một hướng dẫn sao chép luồng) sẽ sửa đổi các tệp nguồn để làm cho chúng tương thích. - Ed999
@ T.Todua Xin chào, lệnh hoạt động tốt khi video không có bản âm thanh. Tuy nhiên, khi myfile1.mp4 không có âm thanh và myfile2.mp4 là với âm thanh, kết quả output.mp4 không có âm thanh. Đầu ra mong đợi.mp4 sẽ chứa âm thanh. Làm thế nào tôi có thể giải quyết nó? - AnswerZhao
@AnswerZhao Tôi nghĩ rằng bạn nên trao đổi thứ tự của tên tập tin trong lệnh .. thay vì file1 | file2, ghi file2 | file1 - T.Todua


CHO PHIM MP4

Dành cho .mp4 các tập tin (mà tôi thu được từ DailyMotion.com: một tập phim truyền hình dài 50 phút, chỉ tải xuống được ba phần, dưới dạng ba tệp .mp4) sau đây là giải pháp hiệu quả cho Windows 7, và làm KHÔNG PHẢI liên quan đến việc mã hóa lại các tệp.

Tôi đã đổi tên các tệp (như file1.mp4, file2.mp4, file3.mp4) sao cho các bộ phận theo đúng thứ tự để xem tập phim truyền hình hoàn chỉnh.

Sau đó, tôi tạo ra một đơn giản tập tin thực thi (concat.bat), với các nội dung sau:

:: Create File List
echo file file1.mp4 >  mylist.txt 
echo file file2.mp4 >> mylist.txt
echo file file3.mp4 >> mylist.txt

:: Concatenate Files
ffmpeg -f concat -i mylist.txt -c copy output.mp4

Các tập tin thực thiffmpeg.exe, cả hai phải được đặt trong cùng một thư mục với .mp4 tệp để được tham gia. Sau đó chạy tập tin thực thi. Thông thường sẽ mất ít hơn mười giây để chạy.


19
2017-12-29 21:36



Các giải pháp dễ nhất cho đến nay. - fredsbend


Tài liệu chi tiết về các cách ghép nối khác nhau trong ffmpeg có thể là tìm thấy ở đây.

Bạn có thể dùng 'Bộ lọc Concat' để nối nhanh.

Nó thực hiện một mã hóa lại. Tùy chọn này là tốt nhất khi đầu vào có định dạng video / âm thanh khác nhau.

Để ghép 2 tệp: 

ffmpeg -i input1.mp4 -i input2.webm \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Để ghép 3 tệp: 

ffmpeg -i input1.mp4 -i input2.webm -i input3.mp4 \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Thao tác này cũng tương tự như nhiều loại tệp đầu vào.


10
2017-10-14 17:30



bạn có thể chỉ định thêm chi tiết về các tùy chọn bạn có trong ví dụ này không? - Developer
@Developer: Để giải thích các tùy chọn -> Wiki lọc concat - SJ00
Khi ghép 3 tệp, bạn nên sử dụng concat = n = 3: v = 1: a = 1 không n = 2 - Cynapsis
Tôi không nhận được kết nối mất mát của tôi ouput.mp4 tốc độ bit của video thấp hơn đáng kể so với tốc độ bit của video đầu vào - jasan
Cảm ơn Cynapsis đã chỉ ra nó và georgiecasey để cập nhật lệnh - SJ00


Đây là một kịch bản tôi đã thực hiện để ghép một số GoPro mp4 vào một 720p mp4. Hy vọng nó giúp đỡ.

#!/bin/sh
cmd="( "
for i; do
    cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}

3
2018-02-11 08:50



mã hóa trung gian không cần thiết - Joe Flateau


dựa trên phản hồi của rogerdpack và Ed999, tôi đã tạo phiên bản .sh

#!/bin/bash

[ -e list.txt ] && rm list.txt
for f in *.mp4
do
   echo "file $f" >> list.txt
done

ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt

nó tham gia tất cả *.mp4 tệp trong thư mục hiện tại vào joined-out.mp4

thử nghiệm trên mac.

kết quả là kích thước chính xác tổng cộng 60 tệp thử nghiệm của tôi. Không được bất kỳ tổn thất nào. Đúng thứ tôi cần


2
2018-02-08 04:52