ฉันมีรายการ.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
ล้มเหลวด้วย OpenSolaris bc
) หรือมีศักยภาพในการใช้หน่วยความจำทั้งหมดในคนอื่น ๆ
avprobe
ใน repos Arch (prolly เพราะมันขัดแย้งกับffmpeg
) ดังนั้นจึงไม่สามารถลองใช้ ATM ได้ แต่จะให้ระยะเวลาของไฟล์หากคุณเรียกใช้เช่นนี้: 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"
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
กับทุกแง่มุมของสถานที่เกิดเหตุบังคับให้สถานที่เกิดเหตุ C มาตรฐานเพื่อที่ฉันจะได้ไม่ต้องกังวลเกี่ยวกับข้อความที่ส่งออกเป็นภาษาท้องถิ่น
ถัดไปฉันใช้เพียงครั้งเดียวแทนเขาawk
grep | grep | head | tr | awk
นั่นawk
ภาวนามองหา (ที่ไม่ซ้ำกันหวังว่า) Duration:
มีเส้น การใช้โคลอนเป็นตัวคั่นป้ายกำกับนั้นคือฟิลด์ 1 ชั่วโมงเป็นฟิลด์ 2 นาทีที่ยื่น 3 และฟิลด์วินาที 4 เครื่องหมายจุลภาคต่อท้ายหลังจากวินาทีดูเหมือนจะไม่รบกวนฉันawk
แต่ถ้ามีคนที่มีปัญหาอยู่ที่นั่น อาจรวมถึงtr -d ,
ในไปป์ไลน์ระหว่างffmpeg
awk
และ
ส่วนนี้มาจาก slm: ฉันใช้paste
เพื่อแทนที่บรรทัดใหม่ด้วยเครื่องหมายบวก แต่ไม่มีผลต่อการขึ้นบรรทัดใหม่ (ตรงกันข้ามกับที่tr \\n +
ฉันมีรุ่นก่อนหน้าคำตอบนี้) ที่ให้ผลรวมของนิพจน์ที่สามารถป้อนbc
ได้
แรงบันดาลใจจากแนวคิดของ slm ที่ใช้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 "วันที่" ที่ได้รับนั้นได้รับการจัดรูปแบบเป็นวันของปีเวลาและนาโนวินาที จากวันนั้นของปีเราลบหนึ่งอันเนื่องจากอินพุตของศูนย์วินาทีนำไปสู่วันที่ 1 ของปี 1970 ฉันไม่คิดว่าจะมีวิธีที่จะทำให้วันนับปีเริ่มต้นที่ศูนย์
สุดท้ายsed
ได้รับการกำจัดศูนย์ต่อท้ายพิเศษ TZ
ตั้งค่าหวังว่าควรบังคับใช้ UTC เพื่อให้ประหยัดเวลากลางวันจะไม่ยุ่งเกี่ยวกับมันคอลเลกชันวิดีโอขนาดใหญ่ หากคุณมีวิดีโอที่มีค่ามากกว่าหนึ่งปีวิธีการนี้ยังคงใช้งานไม่ได้
ฉันไม่คุ้นเคยกับ.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 reverse-polish คลาสสิก:
{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
-show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc
783.493000
เช่น: Appening +
และ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
ในฐานะที่เป็น ubuntu ship libav แทน ffmpeg:
#!/bin/sh
for f in *.mp4; do
avprobe -v quiet -show_format_entry duration "$f"
done | paste -sd+ | bc
ขึ้นอยู่กับแนวคิดMvGอย่างหนัก
วิธีแก้ปัญหาทั้งหมดนี้ต้องใช้งานบ้างสิ่งที่ฉันทำง่ายมาก 1)
ไปที่โฟลเดอร์ที่ต้องการและคลิกขวา -> เปิดด้วยแอปพลิเคชั่นอื่น
จากนั้นเลือก VLC media player
นี่คือตัวอย่าง
คุณสามารถเห็นใต้แถบเครื่องมือมีเพลย์ลิสต์ [10:35:51]ดังนั้นโฟลเดอร์จะมี 10 ชั่วโมง 35 นาทีและ 51 วินาทีในช่วงเวลาของวิดีโอทั้งหมด
ฉันมีไดเรกทอรีย่อยในโฟลเดอร์ปัจจุบันดังนั้นฉันจึงต้องคำนวณระยะเวลาซ้ำ:
find . -iname '*.mp4' -print0 | xargs --null exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n1