Ffmpeg का उपयोग करके फ्रेम निकालने का सबसे तेज़ तरीका?


118

नमस्ते मुझे ffmpeg का उपयोग करके वीडियो से फ़्रेम निकालने की आवश्यकता है .. क्या इससे अधिक तेज़ तरीका है:

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

?


1
^ अपडेट किया गया url: trac.ffmpeg.org/wiki/Seeking
लैम्बार्ट

5
यदि आपके पास सीपीयू चक्र करने के लिए अतिरिक्त है, तो आप समानांतर में कई वीडियो से निकाल सकते हैं:parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
ओले तांगे

जवाबों:


156

यदि JPEG एन्कोडिंग चरण बहुत अधिक प्रदर्शन गहन है, तो आप हमेशा BMP छवियों के रूप में असम्पीडित स्टोर कर सकते हैं:

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

यह भी JPEG के लिए transcoding द्वारा मात्रा का ठहराव के माध्यम से अधिक गुणवत्ता नुकसान नहीं होने का लाभ है। (पीएनजी भी दोषरहित है लेकिन जेपीईजी की तुलना में इसे सांकेतिक शब्दों में बदलने में अधिक समय लगता है।)


9
इससे मेरी मशीन पर बहुत सारे फ्रेम गिरते हैं। क्या मैं सब कुछ प्रस्तुत करने के लिए ffmpeg बता सकता हूं?
Evi1M4chine

45
@ Evi1M4chine सिर्फ -r पैरामीटर को हटा दें यह सभी फ्रेम को निकाल देगा
स्टूडियोज

14
मुझे लगता है कि जबकि JPEG वास्तव में CPU पर मुश्किल नहीं है जोड़ना चाहते हैं, असम्पीडित Bitmaps वास्तव में भंडारण पर बहुत मुश्किल है, इसलिए मुझे संदेह है कि आप JPEG की तुलना में BMP के साथ उच्च throughput मिलेगा।
मार्कस मुलर

4
सभी फ्रेम निकालने के लिए:ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
fiatjaf

10
तुम्हारा मतलब है ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png, है ना? (आप याद आ रहे थे -i)
जोशुआ

68

इस सवाल पर आया था, इसलिए यहाँ एक त्वरित तुलना है। 38m07s वीडियो से प्रति मिनट एक फ्रेम निकालने के लिए इन दो अलग-अलग तरीकों की तुलना करें:

time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp

1m36.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क्योंकि बाद में गलत हो सकता है। यद्यपि टिकट को निर्धारित के रूप में चिह्नित किया गया है , फिर भी मैंने कुछ मुद्दों का अनुभव किया, इसलिए इसे सुरक्षित रूप से खेलना बेहतर है।


6
फ़रवरी 2016: ffmpeg 2.1 के रूप में, सटीक खोज विकल्प अब डिफ़ॉल्ट है - trac.ffmpeg.org/wiki/Seeking
mafrosis

1
bcएक देशी उबंटू पैकेज नहीं है, बजाय एक पार्टी का उपयोग कर सकते हैं: let "i = $i * 60"। BTW - उत्कृष्ट विचार
गिलाद मेयानी

3
-ssपहले जोड़ अच्छा टिप -i। अन्यथा, पूरे वीडियो को डिकोड किया जाएगा और बिना फ़्रेम वाले फ्रेम को छोड़ दिया जाएगा
MoustafaAAtta

2
चूँकि यह Google में सबसे ऊपर है, मैं ध्यान देना चाहूंगा कि 2018 में यह अभी भी एक दृष्टिकोण है जो लाभांश देता है। सबसे अच्छा परिणाम ffmpegआपके मेजबान के एक प्रति कोर के लिए चल रहा है - जो (bmp के लिए) गति में निकट-रैखिक सुधार प्राप्त करता है (जब तक कि आप किसी अन्य अड़चन को नहीं मारते, जैसे कि डिस्क)।
23

यह स्वीकृत उत्तर होना चाहिए, क्योंकि यह प्रश्न 'सबसे तेज़ तरीके' के बारे में है। जाहिर है कि आपको ffprobe का उपयोग करते हुए 'लूप' के लिए बाहर निकलने के चर को जानना होगा जो मुझे लगता है कि अन्य तरीकों की तुलना में अभी भी तेज है।
इम्प्रेम

9

यदि आप वास्तव में जानते हैं कि कौन से फ्रेम को निकालना है, उदाहरण के लिए 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

मैं किसी भी वीडियो से 10 फ्रेम पूर्वावलोकन पाने के लिए Imagemagick के असेंबल के लिए एक पाइप के साथ इसका उपयोग कर रहा हूं। जाहिर है कि फ्रेम संख्या का उपयोग करके आपको यह पता लगाना होगा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

थोड़ा स्पष्टीकरण:

  1. Ffmpeg के भावों में + OR और *AND के लिए हैं
  2. \,बस ,चरित्र से बच रहा है
  3. इसके बिना -vsync vfr -q:v 2काम नहीं लगता, लेकिन मुझे नहीं पता कि क्यों - कोई भी?

4

मैं इसे करने की कोशिश की। 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 लिंक कहां है।
x2212 6

ffmpeg -i file.mpg -vf fps=1 %d.jpg
किशन वाघेला

1

मेरे मामले में मुझे हर सेकंड कम से कम फ्रेम की जरूरत है। मैंने उपर्युक्त दृष्टिकोण के लिए 'तलाश' का इस्तेमाल किया, लेकिन सोचा कि क्या मैं कार्य को समानांतर कर सकता हूं। मैंने यहाँ FIFO दृष्टिकोण के साथ एन प्रक्रियाओं का उपयोग किया: /unix/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 सेकंड तक 'तलाश' को बेहतर बनाया। एकमात्र समस्या मुख्य धागा है जो सफाई से टर्मिनल से बाहर नहीं निकलता है क्योंकि स्टडआउट बाढ़ हो जाता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.