FFmpeg : 비디오를 효율적으로 분할하는 방법은 무엇입니까?


103

큰 avi 비디오를 두 개의 작은 연속 비디오로 나누고 싶습니다. ffmpeg를 사용하고 있습니다.

한 가지 방법은 ffmpeg를 두 번 실행하는 것입니다.

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

그러나 ffmpeg의 맨 페이지에 따르면 줄만 사용하여 하나의 입력 파일에서 둘 이상의 출력 파일을 만들 수 있습니다 .

ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi \
   -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi

내 질문은 나중에 접근하면 계산 시간과 메모리가 절약됩니까?


3
"-vcodec copy -acodec copy"를 사용하면 매우 빠릅니다.))
Savas Adar

@Antony, 두 버전의 시간을 측정하고 (예 :) 메모리 모니터를 살펴보고 htop답이 무엇인지 알려주세요.
AlcubierreDrive '2013

첫 번째 예에서는 순차적으로 수행하고 두 번째 예에서는 스레드를 사용합니다. 둘 다 동일한 작업을 수행하며 눈에 띄는 속도 향상이 발생하지 않아야합니다. : 그러나 단순화 것을, 당신은는 FFmpeg 스트림 분할기의 먹서 사용할 수 있습니다 ffmpeg.org/...
믈라덴 B.

1
이 예는 심하게 잘못 보입니다! ffmpeg 문서는 -ss 옵션에 대해 다음과 같이 설명합니다. "입력 옵션으로 사용되면 (-i 이전),이 입력 파일에서 위치를 찾습니다. 출력 옵션으로 사용되면 (출력 파일 이름 이전), 디코딩하지만 타임 스탬프가 위치에 도달합니다. " 출력 위치에서 사용하고 있으므로 두 번째 라인은 처음 30 분을 디코딩하고 폐기하는 데 시간을 낭비합니다.
Lucian Wischik

1
@LucianWischik이지만 -ss두 번째 분할에서 입력 옵션으로 사용하는 것은 정확하지 않을 수 있으므로 깨끗한 분할을 얻지 못할 수 있습니다. IMO OP의 예가 더 정확합니다.
jiggunjer

답변:


82

ffmpeg 위키는 "비디오를 효율적으로 분할하는 방법"을 참조하여이 페이지로 다시 연결됩니다. 이 페이지가 그 질문에 대한 답을 확신하지 못해서 @AlcubierreDrive가 제안한대로했습니다.

echo "Two commands" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 -sn test1.mkv
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test2.mkv
echo "One command" 
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 \
  -sn test3.mkv -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test4.mkv

어떤 출력이 ...

Two commands
real    0m16.201s
user    0m1.830s
sys 0m1.301s

real    0m43.621s
user    0m4.943s
sys 0m2.908s

One command
real    0m59.410s
user    0m5.577s
sys 0m3.939s

몇 번의 실행과 약간의 수학 후에 SD 및 HD 파일을 테스트했습니다.

Two commands SD 0m53.94 #2 wins  
One command  SD 0m49.63  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.60 #2 wins  
One command  SD 0m58.61 

Two commands SD 0m54.60  
One command  SD 0m50.51 #1 wins 

Two commands SD 0m53.94  
One command  SD 0m49.63 #1 wins  

Two commands SD 0m55.00  
One command  SD 0m52.26 #1 wins 

Two commands SD 0m58.71  
One command  SD 0m58.61 #1 wins

Two commands SD 0m54.63  
One command  SD 0m50.51 #1 wins  

Two commands SD 1m6.67s #2 wins  
One command  SD 1m20.18  

Two commands SD 1m7.67  
One command  SD 1m6.72 #1 wins

Two commands SD 1m4.92  
One command  SD 1m2.24 #1 wins

Two commands SD 1m1.73  
One command  SD 0m59.72 #1 wins

Two commands HD 4m23.20  
One command  HD 3m40.02 #1 wins

Two commands SD 1m1.30  
One command  SD 0m59.59 #1 wins  

Two commands HD 3m47.89  
One command  HD 3m29.59 #1 wins  

Two commands SD 0m59.82  
One command  SD 0m59.41 #1 wins  

Two commands HD 3m51.18  
One command  HD 3m30.79 #1 wins  

SD 파일 = 1.35GB DVB 전송 스트림
HD 파일 = 3.14GB DVB 전송 스트림

결론

HD를 처리하는 경우 단일 명령이 더 낫습니다. '느린 탐색'을 수행하기 위해 입력 파일 뒤에 -ss를 사용하는 것에 대한 매뉴얼 설명에 동의합니다. SD 파일은 미미한 차이가 있습니다.

두 명령 버전은 '빠른 탐색'에 대한 입력 파일 앞에 다른 -ss를 추가 한 다음 더 정확한 느린 탐색을 추가하여 더 빨라야합니다.


TS에 여러 프로그램 (DVB-T로 캡처 한 TV 프로그램)이 포함 된 경우 어떻게 분할 할 수 있습니까? 예를 들어 축구 + 요리 + 만화가 포함 된 TS 파일이 있는데이 TS 파일을 3 mpg 파일로 분할하려면 어떻게해야합니까?
Dr.jacky

여기 내 질문에 답변을 사용 했지만 ( stackoverflow.com/questions/41983940/… ) 작동하지 않았습니다. 내가 뭘 잘못하고 있다고 생각합니까?
utdev

1
제 경우에는 결과 파일에 비디오가 없었습니다 (오디오 만). 몇 번의 실험 후에 나는 영혼을 찾았습니다. 이와 같이 "품질을 수정하지 않음"에 대한 키를 지정해야합니다 -q:v 0.
oklas

19

다음은 자동 분할을 도와주는 유용한 스크립트입니다. ffmpeg를 사용하여 비디오를 분할하는 스크립트

#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
 
function usage {
        echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
        echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
        echo -e "\t - chunk duration must be in seconds"
        echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
        echo -e "\t - if no output filename format is given, it will be computed\
 automatically from input filename"
}
 
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
 
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
 
if [ "$DURATION" = '0' ] ; then
        echo "Invalid input video"
        usage
        exit 1
fi
 
if [ "$CHUNK_LEN" = "0" ] ; then
        echo "Invalid chunk size"
        usage
        exit 2
fi
 
if [ -z "$OUT_FILE_FORMAT" ] ; then
        FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
        FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
        OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
        echo "Using default output file format : $OUT_FILE_FORMAT"
fi
 
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
 
while [ "$OFFSET" -lt "$DURATION" ] ; do
        OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
        echo "writing $OUT_FILE ($N/$N_FILES)..."
        ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
        let "N = N + 1"
        let "OFFSET = OFFSET + CHUNK_LEN"
done

2
SEARAS와 동일한 의견이 있습니다. 배치 파일 작성은 이식성이 없기 때문에 절대적으로 필요할 때나 사용할 수있는 다른 옵션이 없을 때 유용합니다. 예를 들어 Windows에서 동일한 스크립트를 실행할 수 없습니다. 좀 더 일반적인 / 이식 가능한 방법이있는 경우 배치 스크립트를 사용하지 않도록하여 이식에 필요한 시간을 절약해야합니다. ffmpeg에는이 문제를 해결할 수있는 여러 가지 방법이 있으므로 적절한 방법은 스크립트의 도움없이 ffmpeg 만 사용하는 것입니다.
Mladen B.

멋진 스크립트입니다. 당신은 그것을 썼습니까? GitHub에 있습니까? 몇 가지 제안을하고 싶습니다. :)
voices

mp4의 경우 장면이 손상됩니다. -vcodec libx264 -acodec AAC : 더 나은 복사 교체
기슈

8

내 경험상 분할 / 결합에 ffmpeg를 사용하지 마십시오. MP4Box는 ffmpeg보다 빠르고 가볍습니다. 시도해주세요. 예를 들어 1400mb MP4 파일을 700mb의 두 부분으로 분할하려면 다음 cmdl을 사용할 수 있습니다. MP4Box -splits 716800 input.mp4 예를 들어 두 파일을 연결 하려면 다음 을 사용할 수 있습니다.

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4

또는 시간별로 분할해야하는 경우 다음을 사용하십시오 -splitx StartTime:EndTime.

MP4Box -add input.mp4 -splitx 0:15 -new split.mp4


이것이 바로 내가 필요했던 것입니다! ffmpeg로 절단 할 때 클립이 키 프레임에서 시작되지 않고 끝 부분이 이상하게 멈췄습니다. MP4Box -splitz를 사용하여 트릭을 수행했습니다!
matt

1
여러 번호로 Mp4Box를 사용하여 비디오를 어떻게 다듬을 수 있습니까? 예를 들어 몇 초 안에 하위 클립이 필요합니다. 5-8, 21-30, 12-18 그래서 세 개의 출력 비디오 파일이 필요합니다.
mhndev

사용하기 매우 쉽다 EndTime보다는 -t.
vmassuchetto


2

나중에 접근하면 계산 시간과 메모리가 절약됩니까?

귀하가 제공 한 두 가지 예 사이에는 큰 차이가 없습니다. 첫 번째 예제는 비디오를 2 단계로 순차적으로 자르고 두 번째 예제는 스레드를 사용하여 동시에 수행합니다. 특별한 속도 향상은 눈에 띄지 않습니다. FFmpeg로 다중 출력 생성 에 대해 자세히 읽을 수 있습니다.

더 나아가 (최근 FFmpeg에서) 사용할 수있는 것은 다음을 수행 할 수있는 스트림 세그 먼터 muxer 입니다.

거의 고정 된 기간의 여러 개별 파일로 출력 스트림. 출력 파일 이름 패턴은 image2 와 유사한 방식으로 설정할 수 있습니다 .


2

다음은 들어오는 파일을 50 개 부분으로 분할하는 간단한 Windows bat 파일입니다. 각 부분의 길이는 1 분입니다. 그런 멍청한 스크립트에 대해 죄송합니다. 나는 그것을 전혀 가지고 있지 않는 대신 멍청한 Windows 스크립트를 갖는 것이 더 낫기를 바랍니다. 아마도 그것은 누군가를 도울 것입니다. (이 사이트의 "bat file for loop"를 기반으로합니다.)

set var=0
@echo off
:start
set lz=
if %var% EQU 50 goto end
if %var% LEQ 9 set lz=0
echo part %lz%%var%
ffmpeg -ss 00:%lz%%var%:00 -t 00:01:00 -i %1 -acodec copy -vcodec copy %2_%lz%%var%.mp4
set /a var+=1
goto start

:end
echo var has reached %var%.
exit

이것은 본질적 ffmpeg으로 루프로 재 작성된 질문 (연속 명령) 의 첫 번째 코드 조각입니다 . 이것은 그 접근 방식이나 단일 명령이 "계산 시간과 메모리를 절약"하는지에 대한 질문에 대답하지 않습니다.
BACON

1

ist를 테스트하지 않았지만 이것은 유망 해 보입니다.

기본 스트림 분할기

분명히 AVI를 동일한 크기의 세그먼트로 분할하는 것입니다. 이는 이러한 청크가 품질을 떨어 뜨리거나 메모리를 증가시키지 않거나 다시 계산해야 함을 의미합니다.

또한 코덱 복사를 사용합니다. 이는 매우 큰 스트림을 처리 할 수 ​​있음을 의미합니까? 이것이 내 문제이기 때문에 왜곡을 제거하기 위해 필터를 사용할 수 있도록 내 avi를 분해하고 싶습니다. 그러나 전체 avi는 몇 시간 동안 실행됩니다.


-1

다음은 비디오를 분할하는 완벽한 방법입니다. 이전에 해본 적이 있으며 잘 작동합니다.

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (cmd의 경우). shell_exec('ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4')(php 용).

이것을 따르고 완벽하게 작동 할 것이라고 확신합니다.


이것이 비디오를 분할하는 "완벽한 방법"인 이유는 무엇입니까? 질문의 명령 줄과 마찬가지로, 당신은 전달하는 -i다음 -ss-t. 문제는 동일한 입력 파일에서 여러 세그먼트를 효율적으로 추출하는 반면 단일 세그먼트 만 추출하는 방법에 대한 것입니다. 이것이 질문에 어떻게 답하는지 모르겠습니다.
BACON

-2

한 가지 간단한 방법은 publitio url 기반 api 와 함께 trim 옵션을 사용하는 것입니다 .

동영상이 업로드되면 다음과 같이 URL (so_2, eo_2)에 시작 오프셋과 끝 오프셋을 설정하면됩니다.

    https://media.publit.io/file/so_2,eo_2/tummy.mp4

이렇게하면 2 초부터 2 초 길이의 새 동영상이 즉시 생성됩니다. 원하는 방식으로 비디오를 분할 할 수 있습니다.


질문은 .NET을 사용하여 입력 파일에서 여러 세그먼트를 추출하는 두 가지 방법 중 어느 것이 더 효율적인지 묻는 것입니다 ffmpeg. 정말 빠른 인터넷 연결이 아니라면 전체 비디오 를 클라우드 서비스 에 업로드 한 다음 결과다운로드해야 처리 시간이 크게 늘어날 것이라고 생각합니다. 그럼에도 불구하고, 이것은 여전히 접근하는의 질문에 대답하지 않습니다 와 함께ffmpeg 보다 효율적입니다.
BACON
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.