it-swarm.dev

FFmpeg를 사용하여 두 개의 MP4 파일을 연결하는 방법?

Ffmpeg를 사용하여 두 개의 mp4 파일을 연결하려고합니다. 나는 자동 프로세스가 필요하므로 ffmpeg를 선택한 이유가 무엇입니까? 두 파일을 .ts 파일로 변환하고 연결 한 다음 해당 concated .ts 파일을 인코딩하려고합니다. 파일은 h264와 aac으로 인코딩되어 있습니다. 가능한 한 원본과 동일한 품질을 유지하기를 바랍니다.

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

불행히도 나는 인코딩하는 동안 ffmpeg에서 다시 오는 다음 오류 메시지가 나타납니다.

[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

이것은 인코딩의 절반 정도가 발생하여 두 개의 .ts 파일을 연결하여 작동시킬 수 없다고 생각하게 만듭니다.

279
Mark L

나는 mpg를 중간 포맷으로 사용하는 것으로 끝났다. (주의 할 점은 위험한 예이다. -qscale 0은 비디오를 다시 인코딩 할 것이다 ...)

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
30
Mark L

FFmpeg에는 세 가지 연결 방법이 있습니다.

1. 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

이 메서드는 다시 인코딩을 수행합니다.

2. concat demuxer

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

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

Windows 용 :

(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. concat 프로토콜

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

이 방법은 이러한 형식의 본질 및이 방법으로 수행되는 단순한 연결 때문에 MP4를 비롯한 다양한 형식에서 작동하지 않습니다.

어느 것을 사용할 것인가?

  • concat 필터 : 입력 내용이 너비, 높이 등의 매개 변수가 같지 않거나 형식/코덱이 같지 않거나 필터링을 수행하려는 경우에 사용합니다 . (일치하지 않는 입력을 다시 인코딩하여 동일한 코덱 및 기타 매개 변수를 공유 한 다음 다른 입력을 다시 인코딩하지 않도록 concat demuxer를 사용할 수 있습니다).

  • concat demuxer : 재 인코딩을 피하고 형식이 파일 수준 연결을 지원하지 않을 때 사용합니다 (일반 사용자가 사용하는 대부분의 파일은 파일 수준 연결을 지원하지 않습니다).

  • concat 프로토콜 : 파일 수준 연결 (MPEG-1, MPEG-2 PS, DV)을 지원하는 형식과 함께 사용합니다. MP4와 함께 사용하지 마십시오.

의심스러운 경우에는 concat demuxer를 시도하십시오.

또한 보아라.

548
rogerdpack

MP4 파일 용

.mp4 파일 (DailyMotion.com에서 구한 : 50 분짜리 tv 에피소드, 3 부분으로 다운로드 가능, 3 개의 .mp4 비디오 파일로 제공)의 경우 다음을위한 효과적인 해결책이있었습니다. Windows 7 않습니다파일을 다시 인코딩하는 작업을 포함합니다.

파일의 이름을 file1.mp4 , file2.mp4 , file3.mp4 ) 부분이 TV 에피소드 전체를보기 위해 올바른 순서로 표시되도록합니다.

그런 다음 간단한 내용 배치 파일(concat.bat)을 다음과 같은 내용으로 작성했습니다.

:: 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

배치 파일ffmpeg.exe는 모두 .mp4 파일과 같은 폴더에 있어야합니다가 합쳐집니다. 그런 다음 배치 파일을 실행하십시오. 일반적으로 실행하는 데 10 초 미만이 소요됩니다.
.

부록(2018/10/21) -

찾고 있던 내용이 현재 폴더의 모든 mp4 파일을 재 입력하지 않고 지정하는 방법이라면 Windows 배치 파일대신 ( ] _ 반드시 _옵션을 포함해야 함 - 안전 0) :

:: Create File List
for %%i in (*.mp4) do echo file '%%i'>> mylist.txt

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

이것은 Windows 7에서 배치 파일로 작동합니다. 배치 파일에서만 작동하기 때문에명령 행에서 사용하지 마십시오!

50
Ed999

중간 파일이 필요없는 빠른 작업 (1 분 미만 소요)과 무손실 방법이 있습니다.

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

"ls"는 조인 할 파일을 포함합니다. "Perl"은 파이프로 연결 파일을 즉석에서 만듭니다. "-i -"부분은 ffmpeg에게 파이프에서 읽도록 지시합니다

(참고 - 내 파일에는 공백이나 이상한 내용이 없었습니다. "하드"파일로이 아이디어를 수행하려면 쉘 탈출이 필요합니다.).

48
cnd

mP4 파일 :

정확히 동일한 코덱 (동일한 코덱, 동일한 해상도, 동일한 유형)의 MP4 파일이 아니라면 먼저 중간 스트림으로 트랜스 코딩해야합니다.

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

NOTE! : 출력은 첫 번째 파일과 같습니다 (두 번째 파일은 아닙니다)

35
T.Todua

세 개의 .mp3 오디오 파일을 하나의 .m4a 파일에 연결하려고 시도했지만이 ffmpeg 명령이 작동합니다.

입력 명령 :

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

의미 : "-filter_complex concat = n = 3 : v = 0 : a = 1" :

concat 은 media concatenate (join) 함수를 사용함을 의미합니다.
n 은 입력 파일의 총 개수를 확인하는 것을 의미합니다.
v 의미 비디오 ? 0 = 비디오 없음, 1 = 비디오 포함.
a 수단 에는 오디오 가 있습니까? 0 = 오디오 없음, 1 = 오디오 포함.
- f 는 강제 설정 파일 형식을 의미합니다 (지원되는 모든 형식을 보려면 ffmpeg -formats 사용)
- vn 은 비디오 비활성화를 의미합니다 (-an는 원하지 않는 경우 오디오를 비활성화합니다)
- y 는 출력 파일을 겹쳐 쓰는 것을 의미합니다 (출력 파일이 이미있는 경우).

자세한 정보는 다음을 참조하십시오 : ffmpeg -h full를 사용하여 모든 형식 인쇄 (모든 형식 및 코덱 관련 옵션 포함)

32
Ellie Tam

Ffmpeg에서의 다양한 연결 방법에 대한 자세한 문서는 여기 에 있습니다.

빠른 연결을 위해 'Concat filter' 를 사용할 수 있습니다.

다시 인코딩합니다. 이 옵션은 입력이 비디오/오디오 형식이 다를 때 가장 좋습니다.

두 개의 파일을 연결하는 경우 :

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

3 파일 연결 :

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

이는 여러 입력 파일 유형과 동일하게 작동합니다.

11
SJ00

rogerdpack과 Ed999의 답변을 기반으로 .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

현재 폴더의 모든 *.mp4 파일을 joined-out.mp4로 결합합니다

맥에서 테스트.

결과 파일 크기는 테스트 한 60 개의 파일의 정확한 합계입니다. 어떤 손실도 있어서는 안된다. 내가 필요한 것

6

다음 문서에서 : https://trac.ffmpeg.org/wiki/Concatenate

MP4 파일을 가지고 있다면, 먼저 MPEG-2 트랜스 포트 스트림으로 변환하여 무손실 연결할 수 있습니다. H.264 비디오 및 AAC 오디오를 사용하면 다음을 사용할 수 있습니다.

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

이 접근 방식은 모든 플랫폼에서 작동합니다.

크로스 플랫폼 스크립트에서 캡슐화 할 수있는 기능이 필요했기 때문에 fluent-ffmpeg를 사용하여 다음과 같은 해결책을 제시했습니다.

const unlink = path =>
  new Promise((resolve, reject) =>
    fs.unlink(path, err => (err ? reject(err) : resolve()))
  )

const createIntermediate = file =>
  new Promise((resolve, reject) => {
    const out = `${Math.random()
      .toString(13)
      .slice(2)}.ts`

    ffmpeg(file)
      .outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
      .output(out)
      .on('end', () => resolve(out))
      .on('error', reject)
      .run()
  })

const concat = async (files, output) => {
  const names = await Promise.all(files.map(createIntermediate))
  const namesString = names.join('|')

  await new Promise((resolve, reject) =>
    ffmpeg(`concat:${namesString}`)
      .outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
      .output(output)
      .on('end', resolve)
      .on('error', reject)
      .run()
  )

  names.map(unlink)
}

concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
  console.log('done!')
)
4
itslittlejohn

나는 대답 3에서 Mac에서 여러 MP4를 연결하기 위해 옵션 3을 사용할 때 파이프 작동자가 나를 위해 작동하지 않는다는 것을 발견했습니다.

다음 단선은 Mac (High Sierra)에서 작동하여 중간 파일을 만들지 않고도 mp4를 연결합니다.

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4

3
Ben Siver

다음은 몇 가지 GoPro mp4를 720p mp4로 연결하기 위해 만든 스크립트입니다. 희망이 도움이됩니다.

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

이것은 나를 위해 일했습니다 (창문에)

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

특히

ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4

파이썬

많은 파이썬 코드를 사용하여 많은 mp4를 폴더에 넣습니다 import glob import os

stringa = ""
for f in glob.glob("*.mp4"):
    stringa += f + "|"

os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
2
Giovanni Gianni

현재 디렉토리의 모든 mp4 파일 병합

필자는 이후에 삭제해야하는 외부 파일을 생성하지 않으므로 필자의 솔루션은 목록 번호 매기기 파일 (file_1_name, file_2_name, file_10_name, file_20_name, file_100_name ...)

#!/bin/bash
filesList=""
for file in $(ls -1v *.mp4);do #lists even numbered file
    filesList="${filesList}${file}|"
done
filesList=${filesList%?} # removes trailing pipe
ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4
1
Pipo

.mp4 파일의 경우 opensource 명령 줄 도구를 사용하는 것이 더 빠르고 더 효과적이라는 것을 알았습니다 : mp4box. 그런 다음이 방법으로 사용할 수 있습니다.

mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4

대부분의 플랫폼에서 다운로드하십시오 : https://gpac.wp.imt.fr/mp4box/

1
Mario
ffmpeg \
  -i input_1.mp4 \
  -i input_2.mp4 \
  -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
  -map [vid] \
  -c:v libx264 \
  -crf 23 \
  -preset veryfast \
  output.mp4
1
Deepak Kumar

스크립트 아래의 다양한 시도 후 윈도우 10 powershell에 나를 위해 일했다.

    $files=Get-ChildItem -path e:\ -Filter *.mp4


    $files| ForEach-Object  {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII


    if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}

    E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4

    # Conversion Cleanup
    Remove-Item e:\temp.txt

처음 두 줄은 다음 내용이있는 텍스트 파일 temp.txt를 만듭니다.

file 'e:\first.mp4'
file 'e:\second.mp4'

3, 4 행은 ffmpeg가 경로에서 사용 가능한지 확인하고 "joined.mp4"

다른 답변과의 주요 차이점은 다음과 같습니다.

usage  of -bsf:v hevc_mp4toannexb -an

위의 mp4 파일에 대해 비디오 인코딩에 따라 다음과 같은 다른 대안을 사용해야 할 수도 있습니다.

h264_mp4toannexb

이러한 모든 가능한 Bitstream 필터는 https://ffmpeg.org/ffmpeg-bitstream-filters.html 에서 찾을 수 있습니다.

1
rahul maindargi

여기에 설명 된 concat 프로토콜; https://trac.ffmpeg.org/wiki/Concatenate#protocol

중간 파일을 피하기 위해 명명 된 파이프를 사용하여 구현할 때

매우 빠르며 (읽기 : 즉시) 프레임이 떨어지지 않으며 잘 작동합니다.

명명 된 파이프 파일을 삭제하고 비디오가 ffmpeg -i filename.mp4 (h264 및 aac 언급 확인)로 수행 할 수있는 H264 및 AAC인지 확인해야합니다.

0
Roel Van de Paar

다음은 명령 대체 및 concat 비디오 필터를 사용하여 MP4 파일로 가득 찬 디렉토리를 결합하는 방법입니다 (재 인코딩됩니다)-다른 사람이 특히 하나의 파일이있는 경우이 one-liner에서 일부를 사용할 것이라고 생각했습니다. 한 번에 17 개 파일에 합류했습니다) :

ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4

N.B. 이 명령은 파일 이름이 지정된 순서대로 파일을 결합합니다 (예 : ls *.mp4를 실행하면 표시되는 순서와 동일)-제 경우에는 각각 트랙 번호가 있으므로 훌륭하게 작동했습니다.

0
Peter