मेरे पास .ts
फ़ाइलों की एक सूची है :
out1.ts ... out749.ts out8159.ts out8818.ts
मैं इन सभी फाइलों की कुल अवधि (रनिंग टाइम) कैसे प्राप्त कर सकता हूं?
मेरे पास .ts
फ़ाइलों की एक सूची है :
out1.ts ... out749.ts out8159.ts out8818.ts
मैं इन सभी फाइलों की कुल अवधि (रनिंग टाइम) कैसे प्राप्त कर सकता हूं?
जवाबों:
मेरे पास .ts
यहां नहीं है लेकिन यह काम करता है .mp4
। सेकंड में समय पाने के लिए ffprobe
(भाग ffmpeg
) का उपयोग करें , जैसे:
ffprobe -v quiet -of csv=p=0 -show_entries format=duration Inception.mp4
275.690000
.mp4
वर्तमान dir में सभी फ़ाइलों के लिए:
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \;
149.233333
130.146667
275.690000
तब आउटपुटpaste
को पास करने bc
और सेकंड में कुल समय प्राप्त करने के लिए उपयोग करें :
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
555.070000
इसलिए, उन .ts
फ़ाइलों के लिए जिन्हें आप आज़मा सकते हैं:
find . -maxdepth 1 -iname '*.ts' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
एक और उपकरण जो मेरे पास मौजूद वीडियो फ़ाइलों के लिए काम करता है exiftool
, जैसे:
exiftool -S -n Inception.mp4 | grep ^Duration
Duration: 275.69
exiftool -q -p '$Duration#' Inception.mp4
275.69
.mp4
वर्तमान निर्देशिका की सभी फाइलों की कुल लंबाई :
exiftool -S -n ./*.mp4 | awk '/^Duration/ {print $2}' | paste -sd+ -| bc
555.070000000000
exiftool -q -p '$Duration#' ./*.mp4 | awk '{sum += $0}; END{print sum}'
555.070000000000
आप कुल DD:HH:MM:SS
उत्तरों को बदलने के लिए आउटपुट को किसी अन्य कमांड पर भी पाइप कर सकते हैं , यहां उत्तर देखें ।
या उसके लिए exiftool
आंतरिक का उपयोग करें ConvertDuration
(आपको हालांकि अपेक्षाकृत हाल के संस्करण की आवश्यकता है):
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
}' ./*.mp4| tail -n1
0:09:15
ffprobe
से पहले नहीं देखा था ।
paste
और bc
! awk
चलो कहते हैं की तुलना में बहुत क्लीनर ।
bc
मनमानी परिशुद्धता, एक दोष यह है कि ...| paste -sd+ - | bc
या तो कुछ bc
कार्यान्वयन में लाइन आकार सीमा तक पहुंच जाएगा (उदाहरण के लिए seq 429 | paste -sd+ - | bc
ओपनसोलारिस के साथ विफल रहता है bc
) या दूसरों में सभी मेमोरी का उपयोग करने की क्षमता है।
avprobe
आर्क रीपोस में नहीं (संक्षेप में क्योंकि यह संघर्ष करता है ffmpeg
) इसलिए इसे एटीएम की कोशिश नहीं कर सकता है लेकिन क्या यह आपको फ़ाइल की अवधि देता है यदि आप इसे इस तरह से चलाते हैं: avprobe -show_format_entry duration myfile.mp4
या avprobe -loglevel quiet -show_format_entry duration myfile.mp4
? मुझे लगता है कि इनमें से एक कमांड आपको फ़ाइल की अवधि के साथ आउटपुट की एक पंक्ति देनी चाहिए। हालांकि यकीन नहीं हो रहा है।
यह ffmpeg
कुल सेकंड में समय का उपयोग करता है और प्रिंट करता है :
times=()
for f in *.ts; do
_t=$(ffmpeg -i "$f" 2>&1 | grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' ' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }')
times+=("$_t")
done
echo "${times[@]}" | sed 's/ /+/g' | bc
स्पष्टीकरण:
for f in *.ts; do
".ts" में समाप्त होने वाली प्रत्येक फ़ाइल को iterates
ffmpeg -i "$f" 2>&1
आउटपुट को stderr पर पुनर्निर्देशित करता है
grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' '
समय अलग करता है
awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
सेकंड के लिए समय बदलता है
times+=("$_t")
एक सरणी में सेकंड जोड़ता है
echo "${times[@]}" | sed 's/ /+/g' | bc
प्रत्येक तर्क का विस्तार करता है और रिक्त स्थान की जगह लेता है और इसे bc
एक सामान्य लिनक्स कैलकुलेटर पर पाइप करता है
व्यवस्थित बनाने @ jmunsch का जवाब है, और का उपयोग कर paste
मैं बस से सीखा @ SLM का जवाब है, तो आप कुछ इस तरह लग सकती है:
for i in *.ts; do LC_ALL=C ffmpeg -i "$i" 2>&1 | \
awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done | paste -sd+ | bc
जैसे jmunsch ने किया है, मैं ffmpeg
अवधि को प्रिंट करने के लिए उपयोग कर रहा हूं , एक लापता आउटपुट फ़ाइल के बारे में त्रुटि को अनदेखा कर रहा हूं और इसके बजाय अवधि लाइन के लिए त्रुटि आउटपुट खोज रहा हूं । मैं ffmpeg
मानक सी लोकेल के लिए मजबूर लोकेल के सभी पहलुओं के साथ आह्वान करता हूं, ताकि मुझे स्थानीय आउटपुट संदेशों के बारे में चिंता न करनी पड़े।
आगे मैं awk
उसकी जगह सिंगल का इस्तेमाल कर रहा हूं grep | grep | head | tr | awk
। वह awk
मंगलाचरण (उम्मीद से अद्वितीय) युक्त लाइन के लिए दिखता है Duration:
। एक विभाजक के रूप में बृहदान्त्र का उपयोग करना, वह लेबल फ़ील्ड 1 है, घंटे फ़ील्ड 2 हैं, मिनट 3 दर्ज किए गए हैं और सेकंड फ़ील्ड 4. सेकंड के बाद अनुगामी अल्पविराम मुझे परेशान नहीं करता है awk
, लेकिन अगर किसी को वहां समस्या है, तो वह एक शामिल हो सकते हैं tr -d ,
के बीच पाइप लाइन में ffmpeg
और awk
।
अब एसएलएम से भाग आता है: मैं नए paste
संकेतों को प्लस चिह्नों के साथ बदलने के लिए उपयोग कर रहा हूं , लेकिन अनुगामी न्यूलाइन को प्रभावित किए बिना ( इस उत्तर के पिछले संस्करणtr \\n +
में मेरे विपरीत था )। यह योग की अभिव्यक्ति देता है जिसे खिलाया जा सकता है ।bc
date
समय के समान प्रारूपों को संभालने के लिए स्लम के विचार से प्रेरित , यहां एक संस्करण है जो इसे परिणामी सेकंडों को दिनों, घंटों, मिनटों और अंशों वाले सेकंड के रूप में प्रारूपित करने के लिए उपयोग करता है:
TZ=UTC+0 date +'%j %T.%N' --date=@$(for i in *.ts; do LC_ALL=C \
ffmpeg -i "$i" 2>&1 | awk -F: '/Duration:/{print $2*3600+$3*60+$4}'; done \
| paste -sd+ | bc) | awk '{print $1-1 "d",$2}' | sed 's/[.0]*$//'
अंदर $(…)
का हिस्सा पहले की तरह ही है। @
एक संकेत के रूप में चरित्र का उपयोग करते हुए, हम इसे 1 जनवरी 1970 से सेकंड की संख्या के रूप में उपयोग करते हैं। परिणामस्वरूप "तिथि" वर्ष, समय और नैनोसेकंड के दिन के रूप में स्वरूपित हो जाती है। वर्ष के उस दिन से हम एक को घटाते हैं, क्योंकि शून्य सेकंड का एक इनपुट पहले से ही उस वर्ष 1970 के दिन 1 हो जाता है। मुझे नहीं लगता कि शून्य पर शुरू होने वाले वर्ष की गणना का दिन प्राप्त करने का एक तरीका है।
फाइनल sed
में अतिरिक्त ट्रेलिंग शून्य से छुटकारा मिलता है। TZ
सेटिंग उम्मीद है कि, यूटीसी का उपयोग कराने के लिए इतना है कि डेलाइट बचत समय साथ हस्तक्षेप नहीं करेगा चाहिए वास्तव में बड़े वीडियो संग्रह। यदि आपके पास एक वर्ष से अधिक का वीडियो है, तो यह दृष्टिकोण अभी भी काम नहीं करेगा, हालांकि।
मैं .ts
विस्तार से परिचित नहीं हूं , लेकिन यह मानते हुए कि वे किसी प्रकार की वीडियो फ़ाइल हैं ffmpeg
जिसका उपयोग आप किसी फ़ाइल की अवधि की पहचान करने के लिए कर सकते हैं :
$ ffmpeg -i some.mp4 2>&1 | grep Dura
Duration: 00:23:17.01, start: 0.000000, bitrate: 504 kb/s
हम इस उत्पादन को विभाजित कर सकते हैं, केवल अवधि के समय का चयन करते हुए।
$ ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
00:23:17.01
तो अब हमें अपनी फ़ाइलों के माध्यम से पुनरावृति करने और इन अवधि मानों को इकट्ठा करने की आवश्यकता है।
$ for i in *.mp4; do
ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"; done
00:23:17.01
00:23:17.01
00:23:17.01
नोट: यहाँ मेरी उदाहरण के लिए मैं बस अपना नमूना फ़ाइल की नकल की some.mp4
है और इसे नाम दिया है 1.mp4
, 2.mp4
और 3.mp4
।
निम्नलिखित स्निपेट ऊपर से अवधि लेते हैं और उन्हें सेकंड में परिवर्तित करते हैं।
$ for i in *.mp4; do
dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
date -ud "1970/01/01 $dur" +%s; done
1397
1397
1397
यह हमारी अवधि लेता है और $dur
फ़ाइलों के माध्यम से लूप के रूप में उन्हें एक चर में डालता है । इसके date
बाद यूनिक्स एपोक (1970/01/01) साइन सेकंड की संख्या की गणना करने के लिए कमांड का उपयोग किया जाता है। यहाँ ऊपर दिए गए date
आदेश को तोड़ दिया गया है, इसलिए यह देखना आसान है:
$ date -ud "1970/01/01 00:23:17.01" +%s
1397
नोट:date
इस तरीके का उपयोग केवल तभी काम करेगा जब आपकी सभी फाइलों की अवधि <24 घंटे (86400 सेकंड) हो। यदि आपको कुछ ऐसी चीज़ों की ज़रूरत है जो एक बड़ी अवधि को संभाल सकें तो आप इसे विकल्प के रूप में उपयोग कर सकते हैं:
sed 's/^/((/; s/:/)*60+/g' | bc
उदाहरण
$ echo 44:29:36.01 | sed 's/^/((/; s/:/)*60+/g' | bc
160176.01
फिर हम अपने for
लूप का आउटपुट ले सकते हैं और इसे एक paste
कमांड में चला सकते हैं +
, जो प्रत्येक संख्या के बीच में संकेतों को शामिल करेगा , जैसे:
$ for i in *.mp4; do
dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
date -ud "1970/01/01 $dur" +%s; done | paste -s -d+
1397+1397+1397
अंत में हम कमांड लाइन कैलकुलेटर में bc
उन्हें चलाने के लिए इसे चलाते हैं :
$ for i in *.mp4; do
dur=$(ffmpeg -i "$i" 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)");
date -ud "1970/01/01 $dur" +%s; done | paste -s -d+ | bc
4191
सभी फ़ाइलों की कुल अवधि में परिणाम, सेकंड में। यदि आवश्यक हो तो यह निश्चित रूप से किसी अन्य प्रारूप में परिवर्तित किया जा सकता है।
date
अगर ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
कुछ ऐसा है, तो वह चोक हो सकता है 26:33:21.68
(यानी, अवधि, 24 घंटे / 86400 सेकंड)
paste
मेरी पसंदीदा आदेश 8-) है
स्वीकार किए गए उत्तर को बंद करके क्लासिक UNIX रिवर्स-पॉलिश टूल का उपयोग करें:
{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
-show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc
783.493000
Ie: लागू करना +
और p
फिर उस में पाइप करना dc
और आप अपनी राशि प्राप्त करेंगे।
$ find -iname '*.ts' -print0 |\
xargs -0 mplayer -vo dummy -ao dummy -identify 2>/dev/null |\
perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t += $1) && printf "%02d:%02d:%02d:%02d\n",$t/86400,$t/3600%24,$t/60%60,$t%60'
सुनिश्चित करें कि आपके पास MPlayer स्थापित है।
खैर, इन सभी समाधानों को थोड़ा काम करने की ज़रूरत है, जो मैंने किया वह बहुत सरल था, 1)
वांछित फ़ोल्डर में गया और राइट क्लिक -> अन्य एप्लिकेशन के साथ खुला
फिर VLC मीडिया प्लेयर चुनें,
यहाँ उदाहरण है
आप बस टूलबार के नीचे देख सकते हैं, वहां Playlist [10:35:51] लिखा है, इसलिए फ़ोल्डर में 10 घंटे 35 मिनट और कुल वीडियो की 51 सेकंड अवधि है