답변:
JPEG 인코딩 단계가 성능 집약적 인 경우 항상 압축되지 않은 프레임을 BMP 이미지로 저장할 수 있습니다.
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
이것은 또한 JPEG로 트랜스 코딩하여 양자화를 통해 더 많은 품질 손실을 일으키지 않는 장점이 있습니다. (PNG도 무손실이지만 인코딩하는 데 JPEG보다 훨씬 오래 걸리는 경향이 있습니다.)
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
? (당신은 -i
)
이 질문을 보았으므로 여기에 빠른 비교가 있습니다. 38m07s 길이의 비디오에서 분당 하나의 프레임을 추출하는 다음 두 가지 방법을 비교하십시오.
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1 분 36.029s
ffmpeg가 원하는 프레임을 얻기 위해 전체 비디오 파일을 구문 분석하기 때문에 시간이 오래 걸립니다.
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0m4.689s
이것은 약 20 배 더 빠릅니다. 빠른 검색을 사용하여 원하는 시간 인덱스로 이동하고 프레임을 추출한 다음 모든 시간 인덱스에 대해 ffmpeg를 여러 번 호출합니다. 참고 -accurate_seek
기본이고
, 지 확인하십시오 당신은 추가 -ss
입력 비디오하기 전에 -i
옵션을 선택합니다.
그것을 사용하는 것이 좋습니다 것을 참고 -filter:v -fps=fps=...
대신 -r
으로 , 후자는 정확하지 않을 수 있습니다. 티켓이 수정 된 것으로 표시되어 있지만 여전히 몇 가지 문제가 발생 했으므로 안전하게 플레이하는 것이 좋습니다.
bc
기본 Ubuntu 패키지가 아니며 대신 bash :를 사용할 수 있습니다 let "i = $i * 60"
. BTW - 좋은 생각
-ss
전에 추가하는 좋은 팁 -i
. 그렇지 않으면, 전체 비디오 디코딩되고 필수가 프레임이 삭제됩니다
ffmpeg
호스트의 코어 당 하나를 실행하는 것 같습니다. (bmp의 경우) 속도가 거의 선형으로 향상됩니다 (디스크와 같은 다른 병목 현상에 도달 할 때까지).
추출 할 프레임 (예 : 1, 200, 400, 600, 800, 1000)을 정확히 알고있는 경우 다음을 사용해보십시오.
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
나는 이것을 Imagemagick의 몽타주 파이프와 함께 사용하여 모든 비디오에서 10 프레임 미리보기를 얻습니다. 당연히 알아 내야 할 프레임 번호는ffprobe
ffmpeg -i myVideo.mov -vf \
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',scale=320:-1 \
-vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
| montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png
.
약간의 설명 :
+
은 OR 및 *
AND를 나타냅니다.\,
단순히 ,
캐릭터 를 탈출하는 것입니다.-vsync vfr -q:v 2
그것 없이는 작동하지 않는 것 같지만 이유를 모르겠습니다-누구?나는 그것을 시도했다. 32 초에 3600 프레임. 당신의 방법은 정말 느립니다. 당신은 이것을 시도해야합니다.
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
입력 URL이 https 링크 여야하는 곳을 시도하고 있습니다.
ffmpeg -i file.mpg -vf fps=1 %d.jpg
제 경우에는 적어도 1 초마다 프레임이 필요합니다. 위의 '탐색'접근 방식을 사용했지만 작업을 병렬화 할 수 있는지 궁금했습니다. FIFO 접근 방식으로 N 프로세스를 사용했습니다 .https : //unix.stackexchange.com/questions/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
본질적으로 나는 &로 프로세스를 포크했지만 동시 스레드 수를 N으로 제한했습니다.
이로 인해 '탐색'접근 방식이 26 초에서 16 초로 향상되었습니다. 유일한 문제는 stdout이 넘쳐나 기 때문에 메인 스레드가 터미널로 완전히 빠져 나가지 않는다는 것입니다.