एक निर्देशिका में वीडियो फ़ाइलों की कुल अवधि प्राप्त करें


30

मेरे पास .tsफ़ाइलों की एक सूची है :

out1.ts ... out749.ts   out8159.ts  out8818.ts

मैं इन सभी फाइलों की कुल अवधि (रनिंग टाइम) कैसे प्राप्त कर सकता हूं?


आपको किसी एकल फ़ाइल की अवधि कैसे मिलती है?
हौके लैजिंग

मैं यह भी नहीं जानता कि
k961 5

@ हॅक लेजिंग आई ने इस कार्यक्रम को "mediainfo"
k961

ये मीडिया फाइलें, संभावित वीडियो हैं।
स्लम

1
किसी भी मीडिया फाइल (जैसे: MP4, ASF & .264 ...) में पूर्वनिर्धारित मानक हेडर सूचना होगी, हम उस फाइल से जानकारी प्राप्त कर सकते हैं जैसे रिज़ॉल्यूशन, फ्रेम दर, फ्रेम की संख्या (GOP) और फ़ाइल की लंबाई और अवधि मीडिया ...
कांटाम नागेश

जवाबों:


55

मेरे पास .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

बहुत अच्छा, उस चाल w / ffprobeसे पहले नहीं देखा था ।
slm

1
अच्छी चाल के साथ pasteऔर bc! awkचलो कहते हैं की तुलना में बहुत क्लीनर ।
fduff 12

@fduff। जबकि bcमनमानी परिशुद्धता, एक दोष यह है कि ...| paste -sd+ - | bcया तो कुछ bcकार्यान्वयन में लाइन आकार सीमा तक पहुंच जाएगा (उदाहरण के लिए seq 429 | paste -sd+ - | bcओपनसोलारिस के साथ विफल रहता है bc) या दूसरों में सभी मेमोरी का उपयोग करने की क्षमता है।
स्टीफन चेज़लस

क्या आप ऐसा कर सकते हैं (ffprobe मेथड) कुछ एवोकन जैसी चीज के साथ? कुबंटु 14.04 के लिए मेरे रिपॉज में ffmpeg नहीं मिल सकता है - इसलिए मेरे पास ffprobe भी नहीं है? मेरे पास एप्रोब है, लेकिन यह उन तर्कों को पसंद नहीं करता है।
जो

@ जो - avprobeआर्क रीपोस में नहीं (संक्षेप में क्योंकि यह संघर्ष करता है ffmpeg) इसलिए इसे एटीएम की कोशिश नहीं कर सकता है लेकिन क्या यह आपको फ़ाइल की अवधि देता है यदि आप इसे इस तरह से चलाते हैं: avprobe -show_format_entry duration myfile.mp4या avprobe -loglevel quiet -show_format_entry duration myfile.mp4? मुझे लगता है कि इनमें से एक कमांड आपको फ़ाइल की अवधि के साथ आउटपुट की एक पंक्ति देनी चाहिए। हालांकि यकीन नहीं हो रहा है।
don_crissti

6

यह 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एक सामान्य लिनक्स कैलकुलेटर पर पाइप करता है


1
अच्छा! मेरे संस्करण को भी देखें जो आपके विचारों पर भारी है।
MvG

लघु और सुरुचिपूर्ण समाधान
नियो

4

व्यवस्थित बनाने @ 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सेटिंग उम्मीद है कि, यूटीसी का उपयोग कराने के लिए इतना है कि डेलाइट बचत समय साथ हस्तक्षेप नहीं करेगा चाहिए वास्तव में बड़े वीडियो संग्रह। यदि आपके पास एक वर्ष से अधिक का वीडियो है, तो यह दृष्टिकोण अभी भी काम नहीं करेगा, हालांकि।


3

मैं .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

सभी फ़ाइलों की कुल अवधि में परिणाम, सेकंड में। यदि आवश्यक हो तो यह निश्चित रूप से किसी अन्य प्रारूप में परिवर्तित किया जा सकता है।


@DamenSalvatore - कोई बात नहीं, उम्मीद है कि यह आपको दिखाता है कि आप कार्य को विभिन्न चरणों में कैसे तोड़ सकते हैं, इसलिए आप इसे आवश्यकतानुसार अनुकूलित कर सकते हैं।
स्लम

@ एसएलएम - मैं वीडियो की अवधि को सेकंड में परिवर्तित करने के लिए एक और तरीका उपयोग करूंगा क्योंकि dateअगर ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"कुछ ऐसा है, तो वह चोक हो सकता है 26:33:21.68(यानी, अवधि, 24 घंटे / 86400 सेकंड)
don_crissti

@don_crissti - धन्यवाद, मैंने इसे परीक्षण करने के दौरान 20 घंटे से अधिक की कोशिश नहीं की थी। मैं एक वैकल्पिक विधि दिखाते हुए एक नोट जोड़ूंगा।
SLM

आपके उत्तर के लिए धन्यवाद! इससे न केवल मुझे प्रेरणा मिली , बल्कि इसने pasteमेरा ध्यान भी खींचा। मुझे लगता java -classpath $(find -name \*.jar | paste -sd:)है कि मेरे लिए बहुत उपयोगी होने जा रहा है, अतीत में इसके लिए मैंने जिस हैक का इस्तेमाल किया था, उसे देखते हुए।
MvG

@MvG - pasteमेरी पसंदीदा आदेश 8-) है
SLM

1

स्वीकार किए गए उत्तर को बंद करके क्लासिक 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और आप अपनी राशि प्राप्त करेंगे।


2
bcबहुत प्यार मिलता है। आप सभी डाल रहे हैं +प्रत्येक पंक्ति के बीच संकेत (पर शामिल होने +), जबकि रिवर्स पॉलिश के साथ आप सिर्फ एक चक कर सकते हैं +अंत पर और p); इसे बाहर प्रिंट करें
एटी

0
$ 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 स्थापित है।


यह मुझे कोई आउटपुट नहीं देता
k961 6

क्या आपके पास mplayer और perl स्थापित है?
ryanmjacobs

हाँ, मैं mplayer और पर्ल स्थापित पहले से ही स्थापित किया गया था
k961

1
क्षमा करें, मुझे नहीं पता कि यह काम क्यों नहीं कर रहा है; लेकिन, आपके पास पहले से ही पहले से ही काफी अच्छे उत्तर हैं। :)
ryanmjacobs

0

Ubuntu जहाज परिवाद के रूप में ffmpeg के रूप में:

#!/bin/sh
for f in *.mp4; do
    avprobe -v quiet -show_format_entry duration "$f"
done | paste -sd+ | bc

भारी MvG विचारों पर आधारित है


0

खैर, इन सभी समाधानों को थोड़ा काम करने की ज़रूरत है, जो मैंने किया वह बहुत सरल था, 1)

  1. वांछित फ़ोल्डर में गया और राइट क्लिक -> अन्य एप्लिकेशन के साथ खुला

  2. फिर VLC मीडिया प्लेयर चुनें,

  3. यह एक वीडियो खेलना शुरू कर देगा, लेकिन फिर
  4. ctrl + L दबाएं , और आप वीडियो की प्लेलिस्ट देखेंगे और कहीं-कहीं टॉप लेफ्ट कॉर्नर पर आपको कुल अवधि दिखाई देगी

यहाँ उदाहरण है

1। सामग्री सूचीबद्ध करें

2।यहाँ छवि विवरण दर्ज करें

3।यहाँ छवि विवरण दर्ज करें

आप बस टूलबार के नीचे देख सकते हैं, वहां Playlist [10:35:51] लिखा है, इसलिए फ़ोल्डर में 10 घंटे 35 मिनट और कुल वीडियो की 51 सेकंड अवधि है


0

मेरे पास वर्तमान फ़ोल्डर पर उप-निर्देशिकाएं थीं, इसलिए मुझे अवधि की पुनरावृत्ति करने की आवश्यकता थी:

find . -iname '*.mp4' -print0 | xargs --null exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n1

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