मैं FFmpeg का उपयोग करके वीडियो से कई सेगमेंट कैसे निकाल सकता हूं?


40

मैं FFmpeg का उपयोग करके वीडियो के कुछ अनुभागों को हटाने का प्रयास कर रहा हूं।

उदाहरण के लिए, कल्पना करें कि क्या आपने टेलीविज़न पर कोई शो रिकॉर्ड किया है और विज्ञापनों को काट देना चाहते हैं। यह GUI वीडियो-संपादक के साथ सरल है; आप बस हटाए जाने वाले प्रत्येक क्लिप की शुरुआत और अंत को चिह्नित करते हैं, और हटाएं चुनें। मैं कमांड लाइन से FFmpeg के साथ एक ही काम करने की कोशिश कर रहा हूं।

मुझे पता है कि एक सेगमेंट में कटौती कैसे करें नया ऐसे करें वीडियो:

ffmpeg -i input.avi -ss 00:00:20 -t 00:00:05 -map 0 -codec copy output.avi

यह पांच सेकंड की क्लिप को काटता है और इसे एक नई वीडियो फ़ाइल के रूप में सहेजता है, लेकिन मैं इसके विपरीत कैसे कर सकता हूं और पूरे वीडियो को बचा सकता हूं के बिना निर्दिष्ट क्लिप, और मैं कैसे हटाए जाने वाले कई क्लिप निर्दिष्ट कर सकता हूं?

उदाहरण के लिए, यदि मेरा वीडियो ABCDEFG द्वारा प्रस्तुत किया जा सकता है, तो मैं एक नया बनाना चाहूंगा जिसमें ACDFG शामिल होगा।



यह वह नहीं है जो मैं पूछ रहा हूं, मैं यह सब एक "एपिसोड" में प्राप्त करना चाहूंगा, लेकिन मूल वीडियो से अलग अनुभाग होंगे।
Matias

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

@Synetech आपके उत्तर के लिए धन्यवाद। मैं उन्हें अन्य वीडियो के क्लिप के साथ संयोजित नहीं करना चाहता। मैं सिर्फ वीडियो से कुछ हिस्सों को निकालना चाहता हूं। उदाहरण के लिए, यदि मेरा वीडियो ABCDEFG द्वारा प्रस्तुत किया जा सकता है, तो मैं एक नया बनाना चाहूंगा जिसमें ACDFG शामिल होगा।
Matias

@Synetech यह मैं नहीं था, यह आप था जिसे गलत समझा जाना चाहिए था।
Matias

जवाबों:


43

खैर, आप अभी भी उपयोग कर सकते हैं trim उसके लिए फ़िल्टर करें। यहाँ एक उदाहरण है, मान लें कि आप सेगमेंट को 30-40 सेकंड (10 सेकंड) और 50-80 सेकंड (30 सेकंड) काटना चाहते हैं:

ffmpeg -i in.ts -filter_complex \
"[0:v]trim=duration=30[a]; \
 [0:v]trim=start=40:end=50,setpts=PTS-STARTPTS[b]; \
 [a][b]concat[c]; \
 [0:v]trim=start=80,setpts=PTS-STARTPTS[d]; \
 [c][d]concat[out1]" -map [out1] out.ts

मैंने यहाँ क्या किया? मैंने पहले 30 सेकंड, 40-50 सेकंड और 80 सेकंड को समाप्त करने के लिए छंटनी की, और फिर उन्हें स्ट्रीम में संयोजित किया out1 उसके साथ concat फिल्टर।

प्रयासों के बारे में: हमें इसकी आवश्यकता है क्योंकि ट्रिम चित्र प्रदर्शन समय को संशोधित नहीं करता है, और जब हम 10 सेकंड डिकोडर काउंटर को काटते हैं तो इस 10 सेकंड के लिए कोई फ़्रेम नहीं दिखता है।

यदि आप ऑडियो भी चाहते हैं, तो आपको ऑडियो स्ट्रीम के लिए भी ऐसा ही करना होगा। तो कमांड होनी चाहिए:

ffmpeg -i utv.ts -filter_complex \
"[0:v]trim=duration=30[av];[0:a]atrim=duration=30[aa];\
 [0:v]trim=start=40:end=50,setpts=PTS-STARTPTS[bv];\
 [0:a]atrim=start=40:end=50,asetpts=PTS-STARTPTS[ba];\
 [av][bv]concat[cv];[aa][ba]concat=v=0:a=1[ca];\
 [0:v]trim=start=80,setpts=PTS-STARTPTS[dv];\
 [0:a]atrim=start=80,asetpts=PTS-STARTPTS[da];\
 [cv][dv]concat[outv];[ca][da]concat=v=0:a=1[outa]" -map [outv] -map [outa] out.ts

महान एक! हमें सेटिस्फेक्शन की आवश्यकता क्यों है? क्या आप स्पष्टीकरण जोड़ सकते हैं?
Rajib

ठीक है, अद्यतन उत्तर देखें।
ptQa

4
+1 यह वास्तव में उत्तर के रूप में चुना जाना चाहिए। यह "कई सेगमेंट" के लिए अधिक अनुकूल है और एक के बाद एक कई कमांड करने के लिए आवश्यकता को हटाता है। (जब तक कोई अन्य तरीका अधिक गति कुशल न हो)
Knossos

रिकॉर्ड के लिए, जब मैंने सर्वरल सेगमेंट (लगभग 8) के साथ यह कोशिश की, तो मुझे "बफर कतार अतिप्रवाह" के बारे में एक त्रुटि संदेश मिला और कार्यक्रम क्रैश हो गया। मुझे नहीं पता कि कौन से संस्करण इससे प्रभावित हैं, लेकिन मैं इस कारण से इस पद्धति का उपयोग नहीं करना चाहूंगा।
Wutaz

1
जब आप फ्रेम लंघन कर रहे हैं तो आप उपशीर्षक डेटा को बनाए रखने के बारे में क्या करेंगे?
Andrew Scagnelli

12

मुझे काम करने के लिए कभी भी ptQa का समाधान नहीं मिल सकता है, ज्यादातर इसलिए कि मैं कभी भी यह पता नहीं लगा सकता कि फ़िल्टर से त्रुटियों का क्या मतलब है या उन्हें कैसे ठीक किया जाए। मेरा समाधान थोड़ा अव्यवस्थित लगता है क्योंकि यह एक गड़बड़ को पीछे छोड़ सकता है, लेकिन यदि आप इसे एक स्क्रिप्ट में फेंक रहे हैं, तो सफाई को स्वचालित किया जा सकता है। मुझे यह दृष्टिकोण भी पसंद है क्योंकि अगर चरण 4 पर कुछ गलत होता है, तो आप 1-3 चरणों को पूरा करते हैं, इसलिए त्रुटियों से उबरना थोड़ा अधिक कुशल है।

मूल रणनीति का उपयोग कर रहा है -t तथा -ss अपने इच्छित प्रत्येक खंड के वीडियो प्राप्त करने के लिए, फिर अपने अंतिम संस्करण के लिए सभी भागों को एक साथ मिलाएं।

मान लें कि आपके पास प्रत्येक 5 सेकंड में 6 खंड ABCDEF हैं और आप A (0-5 सेकंड), C (10-15 सेकंड) और E (20-25 सेकंड) चाहते हैं:

ffmpeg -i abcdef.tvshow -t 5 a.tvshow -ss 10 -t 5 c.tvshow -ss 20 -t 5 e.tvshow

या

ffmpeg -i abcdef.tvshow -t 0:00:05 a.tvshow -ss 0:00:10 -t 0:00:05 c.tvshow -ss 0:00:20 -t 0:00:05 e.tvshow

जो फाइलों को a.tv शो, c.tvshow और e.tv शो बना देगा। -t कहता है कि प्रत्येक क्लिप कितनी लंबी है, इसलिए यदि c 30 सेकंड लंबा है तो आप 30 या 0:00:30 में पास कर सकते हैं। -ss विकल्प कहता है कि स्रोत वीडियो में कितनी दूर छोड़ना है, इसलिए यह हमेशा फ़ाइल की शुरुआत के सापेक्ष है।

फिर एक बार जब आपके पास वीडियो फ़ाइलों का एक गुच्छा होता है, तो मैं एक फ़ाइल बनाता हूं ace-files.txt इस तरह:

file 'a.tvshow'
file 'c.tvshow'
file 'e.tvshow'

शुरुआत में "फ़ाइल" पर ध्यान दें और उसके बाद बच गए फ़ाइल का नाम।

फिर कमांड:

ffmpeg -f concat -i ace-files.txt -c copy ace.tvshow

वह सभी फाइलों को सम्‍मिलित करता है abe-files.txt साथ में, उनके ऑडियो और वीडियो कोडेक्स को कॉपी करके एक फाइल बनाता है ace.tvshow जो कि सिर्फ a, c और e सेक्शन होना चाहिए। फिर बस हटाना याद है ace-files.txt, a.tvshow, c.tvshow तथा e.tvshow

अस्वीकरण : मुझे नहीं पता कि कैसे (में) कुशल इस मामले में अन्य दृष्टिकोणों की तुलना में है ffmpeg लेकिन मेरे उद्देश्यों के लिए यह बेहतर काम करता है। आशा है कि यह किसी की मदद करता है।


1
यह मेरे लिए newbies के लिए बहुत समझ में आता है, धन्यवाद
juanpastas

2
ध्यान दें कि यदि आप बैश का उपयोग कर रहे हैं, तो आप फ़ाइल के निर्माण से बच सकते हैं ( ace-files.txt आपके उदाहरण में): ffmpeg -f concat -i <(printf "file '%s'\n" $(pwd)/prefix_*.tvshow) -c copy output.tvshow
bufh

यह वास्तव में उपयोगी था, लेकिन मुझे फ़ाइल नामों के आसपास से एकल उद्धरण को हटाना पड़ा या यह काम नहीं किया।
tchaymore

2

यद्यपि ptQa द्वारा प्रदान किया गया उत्तर काम करने लगता है, मैंने एक अन्य समाधान विकसित किया है जो ठीक काम करने के लिए प्रचलित है।

मूल रूप से, मैं जो कुछ करता हूं, वह मूल वीडियो के प्रत्येक भाग के लिए एक वीडियो को काटने के लिए होता है जिसे मैं अपने परिणाम में शामिल करना चाहता हूं। बाद में, मैं उन्हें कॉनैट डिमॉक्सर के साथ समझाता हूं यहाँ

समाधान एक ही है कि मैंने पहले क्या कोशिश की है और सिंक समस्याएं प्रस्तुत की हैं। मैंने जो जोड़ा है वह कमांड है -वेद_नेत्र_से १ विभिन्न वीडियो बनाते समय। इस समाधान के साथ, सिंक समस्याएं गायब हो जाती हैं।


1

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

  • एक या कई खंड लें।
  • आप सेगमेंट को एक परिणामी फ़ाइल में जोड़ सकते हैं।
  • ज्वाइन करने के बाद आप पार्ट फाइल्स को रख या हटा सकते हैं।
  • आप मूल फ़ाइल रख सकते हैं या इसे अपनी नई फ़ाइल से बदल सकते हैं।

कार्रवाई में इसका वीडियो: यहाँ

आप क्या सोचते हैं मुझे बताओ।

 #!/bin/bash
/bin/date >>segmenter.log

function segment (){
while true; do
    echo "Would you like to cut out a segment ?"
    echo -e "1) Yes\n2) No\n3) Quit"
    read CHOICE
    if [ "$CHOICE" == "3" ]; then
        exit
    elif [ "$CHOICE" == "2" ]; then
        clear
        break
    elif [ "$CHOICE" == "1" ]; then
        clear
        ((segments++))
        echo "What time does segment $segments start ?"
        read SEGSTART
        clear
        echo -e "Segment $segments start set to $SEGSTART\n"  
        echo "What time does segment $segments end ?"
        read SEGEND
        clear
        echo -e "Segment $segments end set to $SEGEND\n"
        break
    else
        clear
        echo -e "Bad option"
        segment "$segments"
    fi
done
if [ "$CHOICE" == "1" ]; then
    echo "Cutting file $file video segment $segments starting at $SEGSTART and ending at $SEGEND"
    ffmpeg -i "$file" -ss $SEGSTART -to  $SEGEND -map 0:0 -map 0:1 -c:a copy -c:v copy  "$filename-part$segments.$extension"  >> segmenter.log 2>&1
    clear
    echo -e "Cut file $filename-part$segments.$extension starting at $SEGSTART and ending at $SEGEND\n"                             
    segment "$segments"
fi
}

file="$1"
filename="${file%.*}"
extension="${file##*.}"
clear
segments=0
segment "$segments"
clear
if (("$segments"==1)); then
mv $filename"-part1."$extension "$filename-segmented.$extension"
elif (("$segments">1)); then
echo "Would you like to join the segments into one file ?"      
       OPTIONS="Yes No Quit"
       select opt in $OPTIONS; do
       clear
        if [ "$opt" == "Quit" ]; then
            exit
        elif [ "$opt" == "Yes" ]; then
            clear
            echo "Joining segments"
            ffmpeg -f concat -i <(for f in $filename"-part"*$extension;         do echo "file '$(pwd)/$f'"; done) -c:a copy -c:v copy "$filename-segmented.$extension" >>         segmenter.log 2>&1
            clear
            echo "Would you like to delete the part files ?"
            select opt in $OPTIONS; do
            clear
            if [ "$opt" == "Quit" ]; then
                exit
            elif [ "$opt" == "Yes" ]; then
                for f in $filename"-part"*$extension; do rm $f; done
                break
            elif [ "$opt" == "No" ]; then
                break
            else
                clear
                echo -e "Bad option\n"
            fi
            done
            break
        clear
        elif [ "$opt" == "No" ]; then
            exit
        else
            clear
            echo -e "Bad option\n"
        fi
    done
fi
echo "Would you like to replace the original file with the result of your changes ?"
OPTIONS="Yes No Quit"
select opt in $OPTIONS; do
    clear
    if [ "$opt" == "Quit" ]; then
        exit
    elif [ "$opt" == "Yes" ]; then
        rm $file
        mv "$filename-segmented.$extension" $file
        break
    elif [ "$opt" == "No" ]; then
        break
    else
        clear
        echo -e "Bad option\n"
    fi
done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.