Programing

ffmpeg를 사용하여 프레임을 추출하는 가장 빠른 방법은 무엇입니까?

lottogame 2020. 8. 28. 07:47
반응형

ffmpeg를 사용하여 프레임을 추출하는 가장 빠른 방법은 무엇입니까?


안녕하세요, ffmpeg를 사용하여 동영상에서 프레임을 추출해야합니다. 이보다 빠른 방법이 있습니까?

ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg

?


JPEG 인코딩 단계가 성능 집약적 인 경우 항상 압축되지 않은 프레임을 BMP 이미지로 저장할 수 있습니다.

ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp

이것은 또한 JPEG로 트랜스 코딩하여 양자화를 통해 더 많은 품질 손실을 일으키지 않는 장점이 있습니다. (PNG도 무손실이지만 인코딩하는 데 JPEG보다 훨씬 오래 걸리는 경향이 있습니다.)


이 질문을 보았으므로 여기에 빠른 비교가 있습니다. 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으로 , 후자는 정확하지 않을 수 있습니다. 티켓이 수정 된 것으로 표시되어 있지만 여전히 몇 가지 문제가 발생 했으므로 안전하게 플레이하는 것이 좋습니다.


추출 할 프레임 (예 : 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\,100)',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

.

약간의 설명 :

  1. ffmpeg에서 표현식 +은 OR 및 *AND를 나타냅니다.
  2. \,단순히 ,캐릭터 를 탈출하는 것입니다.
  3. -vsync vfr -q:v 2그것 없이는 작동하지 않는 것 같지만 이유를 모르겠습니다-누구?

나는 그것을 시도했다. 32 초에 3600 프레임. 당신의 방법은 정말 느립니다. 이것을 시도해야합니다.

ffmpeg -i file.mpg -s 240x135 -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으로 제한했습니다.

This improved the 'seek to' approach from 26 seconds to 16 seconds in my case. The only problem is the main thread does not exit cleanly back to the terminal since stdout gets flooded.

참고URL : https://stackoverflow.com/questions/10957412/fastest-way-to-extract-frames-using-ffmpeg

반응형