FFmpeg के साथ दिए गए टाइमस्टैम्प से पहले निकटतम कीफ़्रेम का समय स्टैम्प कैसे प्राप्त करें?


18

मैं एक FFmpeg चाहता हूं जो तेज और सटीक कमांड की मांग कर रहा है। मुझे यह मिल गया ।

समाधान यह है कि हम -ssइनपुट (तेजी से मांग) और आउटपुट (सटीक मांग) दोनों के लिए आवेदन करते हैं। लेकिन: यदि मांगने वाला इनपुट सटीक नहीं है, तो हम कैसे सुनिश्चित कर सकते हैं कि मांगने की स्थिति सटीक है?


उदाहरण के लिए: अगर हम 00:03:00 पर जाना चाहते हैं, तो कमांड कुछ इस तरह है:

ffmpeg -ss 00:02:30 -i <INPUT> ... -ss 00:00:30 <OUTPUT>

पहले -ssकहीं और की तलाश में होगा, नहीं 00:02:30, कहते हैं 00:02:31। और दूसरी तलाश में आवेदन करने के बाद अंतिम परिणाम होगा 00:03:01- वह नहीं जो हम चाहते हैं। क्या वो सही है?

पहली -ssतलाश कहाँ करता है? क्या यह उस केफ्रेम की तलाश में है जो सबसे नजदीक है 00:02:30?

यदि ऐसा है, तो यहां मेरा विचार है - गलत होने पर मुझे सही करें: पहली मांग के बाद, हमें परिणाम का टाइमस्टैम्प मिलता है (इस उदाहरण में:) 00:02:31, तो हम इस मामले में, उपयुक्त समय के साथ दूसरी मांग को लागू करते हैं 00:00:29

प्रश्न है: हमें पहले शोध परिणाम का समय स्टैंप कैसे मिलता है?

जवाबों:


18

शाब्दिक रूप से आपके शीर्षक के प्रश्न का उत्तर देने के लिए: आप के साथ आई-फ्रेम्स की एक सूची प्राप्त कर सकते हैं

ffprobe -select_streams v -show_frames <INPUT> 

आप इसे आगे बढ़ाकर आवश्यक आउटपुट तक सीमित कर सकते हैं -show_entries frame=pkt_pts_time,pict_type

यह देखने के लिए कि कौन सा फ्रेम निकटतम है (एक निश्चित टाइमस्टैम्प के बाद), आपको सबसे पहले keyframes के सभी टाइमस्टैम्प का पता लगाना होगा, उदाहरण के लिए awk

सबसे पहले, उस समय को परिभाषित करें जिसे आप देखना चाहते हैं, उदाहरण के लिए, 2: 30 मीटर जो 150 के बराबर है।

ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet in.mp4 | 
awk -F= ' 
  /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } } 
  /pkt_pts_time/ { if (i && ($2 >= 150)) print $2; }  
' | head -n 1

उदाहरण के लिए, यह वापस आ जाएगा 150.400000


ध्यान दें कि -ssपहले उपयोग करते समय -i, FFmpeg कीप पॉइंट पर पिछले की- बोर्ड का पता लगाएगा , फिर नकारात्मक PTS मानों को निम्नलिखित सभी फ़्रेमों तक असाइन करें, जब तक कि वह खोज बिंदु तक नहीं पहुँच जाता। एक खिलाड़ी को डिकोड होना चाहिए, लेकिन नकारात्मक पीटीएस के साथ फ़्रेम प्रदर्शित नहीं करना चाहिए, और वीडियो को सटीक रूप से शुरू करना चाहिए।

कुछ खिलाड़ी इसका ठीक से सम्मान नहीं करते हैं और काला वीडियो या कचरा प्रदर्शित करेंगे। इस स्थिति में, उपरोक्त स्क्रिप्ट का उपयोग आपके खोज बिंदु के बाद कीफ़्रेम के पीटीएस को खोजने के लिए किया जा सकता है , और किफ़्रेम से मांग शुरू करने के लिए इसका उपयोग करें। यह, हालांकि, सटीक नहीं होगा।

ध्यान दें कि यदि आप मांग करते समय सुपर सटीक होना चाहते हैं - और कई खिलाड़ियों के साथ संगतता बनाए रखना है - तो आपको वीडियो को किसी भी दोषरहित, अंतर-केवल प्रारूप में परिवर्तित करना चाहिए, जहां आप किसी भी बिंदु पर काट सकते हैं, और फिर इसे फिर से एनकोड कर सकते हैं। लेकिन यह उपवास नहीं होगा।


1
धन्यवाद, मैं एक वीडियो संपादक नहीं बना रहा हूं, लेकिन मैं सटीक वीडियो की मांग करना चाहता हूं जिसमें अंतर 0,5 सेकंड से कम होना चाहिए।
कटहल

1
आप शायद पीटीएस के आसपास से जुगाड़ कर सकते हैं ffprobe। यदि नहीं, तो कोई भी मध्यवर्ती प्रारूप होगा, उदाहरण के लिए Prores 422, DNxHD, जो केवल नेत्रहीन दोषरहित और इंट्रा-फ्रेम हैं। या आप HuffYUV, आदि जैसे कुछ का उपयोग करते हैं, लेकिन फिर आप "फास्ट" पहलू को फिर से खो देंगे, बिल्कुल।
slhck

ffprobe के किस संस्करण का उपयोग आपने कमांड के लिए किया था, क्योंकि मेरा कहना हैUnrecognized option 'select_streams'
कटक

2
आप करीब थे, अक्टूबर 2012 मेंselect_streams विकल्प जोड़ा गया था । :) आप इसके बिना कर सकते थे, लेकिन फिर आपको ऑडियो फ्रेम के लिए भी जानकारी मिलेगी, बीच में मिलाया जाएगा।
slhck

2
ध्यान दें कि आप इस ffmpeg लाइन को जोड़ सकते हैं ताकि केवल आवश्यक 2 फ़ील्ड को आउटपुट कर सकें, बहुत सारे सामान के बजाय जो कि awk द्वारा फेंका जाता है: -show_entries फ्रेम = pkt_pts_time, pict_type
Jannes

7

मैं समझता हूं कि यह सवाल कई साल पुराना है, लेकिन ffprobe के नवीनतम संस्करण में फ्रेम को छोड़ने की क्षमता है । आप -skip_frame nokeyकेवल मुख्य फ़्रेम (I- फ़्रेम) पर जानकारी रिपोर्ट करने के लिए पास कर सकते हैं । इससे आपका बहुत समय बच सकता है! 2GB 1080p MP4 फ़ाइल पर इसे स्किप फ्रेम के बिना 4 मिनट लगते थे। स्किप पैरामैटर को जोड़ने में केवल 20 सेकंड लगते हैं।

कमान:

ffprobe -select_streams v -skip_frame nokey -show_frames -show_entries फ्रेम = pkt_pts_time, pict_type D: \ test.mp4

परिणाम:

[FRAME]
pkt_pts_time=0.000000
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=3.753750
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=7.507500
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=11.261250
pict_type=I
[/FRAME]
[FRAME]
pkt_pts_time=15.015000
pict_type=I
[/FRAME]

इसलिए परिणामों में केवल मुख्य फ़्रेमों के बारे में जानकारी होगी।


1

स्लैक के उत्तर पर निर्माण , यहां एक बैश फ़ंक्शन है जो निकटतम कीफ्रेम लौटाएगा जो कि BEFORE Nसेकंड में होता है ।

यह यह -read_intervalsसुनिश्चित करने के लिए भी उपयोग करता है कि ffprobe केवल सेकंड से 25 सेकंड पहले अपने keyframe की तलाश शुरू कर देता है N। टाइमस्टैम्प मिलने पर यह ट्रिक और एक्जिट एग्जिट होने से चीजों को गति मिलती है।

function ffnearest() {
  STIME=$2; export STIME;
  ffprobe -read_intervals $[$STIME-25]% -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet "$1" |
  awk -F= '
    /pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
    /pkt_pts_time/ { if (i && ($2 <= ENVIRON["STIME"])) print $2; }
    /pkt_pts_time/ { if (i && ($2 > ENVIRON["STIME"])) exit 0; }
  ' | tail -n 1
}

उदाहरण का उपयोग:

➜ ffnearest input.mkv 30
23.941000

मैं उन्हें फिर से एन्कोडिंग के बिना वीडियो फ़ाइलों को ट्रिम करने के लिए इसका उपयोग करता हूं। चूँकि आप पुन: एन्कोडिंग के बिना नए कीफ्रेम नहीं जोड़ सकते हैं, मैं ffnearestइससे पहले कि मैं कटना चाहूँ, कीफ्रेम की तलाश करूँगा। यहाँ एक उदाहरण है:

ffmpeg  -i input.mkv -ss 00:00:$(echo "$(ffnearest input.mkv 30) - 0.5" | bc)  -c copy -y output.mkv;

ध्यान दें कि उस उदाहरण के लिए आपको -ssपहले 60 सेकंड की तुलना में आगे बढ़ने की स्थिति में परम में पारित किए गए प्रारूप को बदलने की आवश्यकता हो सकती है ।

(झुंझलाहट, ffmpeg को keyframe के टाइमस्टैम्प की तलाश करने के लिए कहने से लगता है कि आउटपुट में किफ़्रेम को बाहर करना है, लेकिन कीफ़्रेम के वास्तविक टाइमस्टैम्प से 0.5 सेकंड घटाना ट्रिक करता है। bash के लिए आपको bcदशमलव के साथ अभिव्यक्तियों का मूल्यांकन करने के लिए उपयोग करने की आवश्यकता होती है। , लेकिन zsh में -ss 00:00:$[$(ffnearest input.mkv 28)-0.5]काम करता है।)


यह अगले फ्रेम समय मैं फ्रेम के बाद दे देंगे।
एहसान चावोशी

0

यदि आप I फ्रेम की जानकारी प्राप्त करना चाहते हैं, तो आप उपयोग कर सकते हैं

ffprobe -i input.mp4 -v quiet -select_streams v -show_entries frame=pkt_pts_time,pict_type|grep -B 1 'pict_type=I'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.