Bir .ts
dosya listem var :
out1.ts ... out749.ts out8159.ts out8818.ts
Tüm bu dosyaların toplam süresini (çalışma süresini) nasıl alabilirim?
Bir .ts
dosya listem var :
out1.ts ... out749.ts out8159.ts out8818.ts
Tüm bu dosyaların toplam süresini (çalışma süresini) nasıl alabilirim?
Yanıtlar:
Hiç var .ts
burada ama bunun için çalışır .mp4
. Kullanım ffprobe
(parçası ffmpeg
) saniye, örneğin zaman almak için:
ffprobe -v quiet -of csv=p=0 -show_entries format=duration Inception.mp4
275.690000
.mp4
geçerli dizindeki tüm dosyalar için :
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \;
149.233333
130.146667
275.690000
Daha sonra kullanmak paste
üzere çıktıyı geçmesi için bc
ve saniye cinsinden toplam zaman olsun:
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
555.070000
Yani, .ts
deneyebileceğiniz dosyalar için :
find . -maxdepth 1 -iname '*.ts' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
Burada sahip olduğum video dosyaları için çalışan başka bir araç exiftool
, örneğin:
exiftool -S -n Inception.mp4 | grep ^Duration
Duration: 275.69
exiftool -q -p '$Duration#' Inception.mp4
275.69
.mp4
Geçerli dizindeki tüm dosyaların toplam uzunluğu :
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
Ayrıca başka bir komuta çıkış için toplam dönüştürmek olabilir DD:HH:MM:SS
, cevapları görmek burada .
Ya kullanımı exiftool
'iç s ConvertDuration
(gerçi nispeten yeni bir sürümü gerekir) bunun için:
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
}' ./*.mp4| tail -n1
0:09:15
ffprobe
.
paste
ve bc
! awk
Diyelim ki çok daha temiz .
bc
İsteğe bağlı bir kesinliği olsa da, bazı dezavantajlar ...| paste -sd+ - | bc
bazı bc
uygulamalarda (örneğin seq 429 | paste -sd+ - | bc
OpenSolaris ile başarısız bc
) satır boyut sınırına ulaşması veya diğerlerinde tüm belleği kullanma potansiyeline sahip olmasıdır.
avprobe
, Arch depolarında (bununla çakıştığı için ffmpeg
) çünkü ATM'yi deneyemezsiniz, ancak eğer böyle çalıştırırsanız dosyanın süresini veriyor mu : avprobe -show_format_entry duration myfile.mp4
veya avprobe -loglevel quiet -show_format_entry duration myfile.mp4
? Bence bu komutlardan biri size dosyanın süresi boyunca tek bir çıktı satırı vermeli. Emin değilim.
Bu ffmpeg
, zaman aşımını toplam saniye olarak kullanır ve yazdırır:
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
Açıklama:
for f in *.ts; do
".ts" ile biten her bir dosyayı yineler
ffmpeg -i "$f" 2>&1
çıktıyı stderr'ye yönlendirir
grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' '
zamanı izole eder
awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
Zamanı saniye'ye çevirir
times+=("$_t")
bir diziye saniye ekler
echo "${times[@]}" | sed 's/ /+/g' | bc
Argümanların her birini genişletir ve boşlukları değiştirir ve onu bc
ortak bir linux hesaplayıcısına aktarır
Düzene jmunsch cevabı @ ve kullanma paste
sadece öğrenilen I @ slm cevabı , böyle bir şey ile bitebileceğini:
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
Tıpkı jmunsch gibi, ffmpeg
süreyi yazdırmak için kullanıyorum , eksik bir çıktı dosyası ile ilgili hatayı görmezden geliyorum ve bunun yerine süre satırı için hata çıktısını araştırıyorum. Ben çağırmak ffmpeg
ben lokalize çıkış mesajları hakkında endişe zorunda kalmazsınız böylece, Standart C yerelinde zorla yerel ayar tüm yönleri ile.
Sonra awk
onun yerine bir tane kullanıyorum grep | grep | head | tr | awk
. Bu awk
çağrı içeren (umarım benzersiz) bir çizgi arar Duration:
. Ayırıcı olarak iki nokta üst üste kullanarak, bu etiket alanı 1, saatleri alanı 2, dakika Sondaki virgül gözlerimi rahatsız görünmüyor saniye sonra 3 ve saniye alanını 4. dosyalanmış olan awk
, ancak birileri sorunları varsa, o ve tr -d ,
arasındaki boru hattına bir içerebilir .ffmpeg
awk
Şimdi slm'den gelen bölüm geliyor: paste
yeni satırları artı işaretleriyle değiştirmek için kullanıyorum , ancak sondaki yeni satırı etkilemeden kullanıyorum (aksine bu cevabın önceki sürümündetr \\n +
bulundum ). Bu, beslenebilecek toplam ifadesini verir .bc
Slm'in date
zamana benzer formatları kullanmak için kullanma fikrinden esinlenerek , burada elde edilen saniyeleri kesirli kısımlarla gün, saat, dakika ve saniye olarak formatlamak için kullanan bir versiyon:
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]*$//'
İçindeki kısım $(…)
tam olarak eskisi gibi. @
Karakteri bir gösterge olarak kullanarak , bunu 1 Ocak 1970'ten bu yana geçen saniye sayısı olarak kullanırız. Sonuçta ortaya çıkan “tarih”, yılın günü, saati ve nanosaniye olarak biçimlendirilir. Yılın o gününden bir tanesini çıkardık, çünkü sıfır saniyelik bir girdi zaten o yılın 1970'in 1. gününe yol açtı. Sıfırdan başlayarak yılın gününü almanın bir yolu olduğunu sanmıyorum.
Final sed
, sondaki sıfırlardan kurtulur. Bu TZ
ayar UTC kullanımını zorlamalıdır, böylece gün ışığından yararlanma saati gerçekten büyük video koleksiyonlarına engel olmaz . Bir yıldan fazla video değeriniz varsa, bu yaklaşım yine de işe yaramaz.
Uzantıya aşina değilim .ts
, ancak ffmpeg
böyle bir dosyanın süresini belirlemek için kullanabileceğiniz bir tür video dosyası olduğunu varsayalım:
$ ffmpeg -i some.mp4 2>&1 | grep Dura
Duration: 00:23:17.01, start: 0.000000, bitrate: 504 kb/s
Daha sonra sadece süreyi seçerek bu çıktıyı bölebiliriz.
$ ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
00:23:17.01
Şimdi sadece dosyalarımızı gözden geçirmek ve bu süre değerlerini toplamak için bir yola ihtiyacımız var.
$ 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
NOT: İşte benim mesela ben sadece benim örnek dosyayı kopyalanmış some.mp4
ve onu adlandırılmış 1.mp4
, 2.mp4
ve 3.mp4
.
Aşağıdaki kod parçası süreleri yukarıdan alacak ve saniyelere çevirecektir.
$ 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
Bu bizim sürelerimizi alır $dur
ve dosyaları değiştirirken bunları değişkene koyar . date
Komut daha sonra UNIX dönemine (1970/01/01) sinüs saniye sayısını hesaplamak için kullanılır. İşte yukarıdaki date
komut dağıldı, bu yüzden görülmesi daha kolay:
$ date -ud "1970/01/01 00:23:17.01" +%s
1397
NOT:date
Bu şekilde kullanmak , tüm dosyalarınızın <24 saat (yani 86400 saniye) süresine sahip olması durumunda işe yarar. Daha büyük sürelerle başa çıkabilecek bir şeye ihtiyacınız olursa, bunu alternatif olarak kullanabilirsiniz:
sed 's/^/((/; s/:/)*60+/g' | bc
Örnek
$ echo 44:29:36.01 | sed 's/^/((/; s/:/)*60+/g' | bc
160176.01
Daha sonra for
döngümüzün çıktısını alabilir ve her sayı arasında işaretleri paste
içeren bir komuta girebiliriz +
, şöyle:
$ 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
Sonunda, bc
bunları özetlemek için komut satırı hesap makinesine koyarız :
$ 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
Tüm dosyaların toplam süresi içinde saniye cinsinden sonuç. Elbette gerekirse bu başka bir formata dönüştürülebilir.
date
might 24 saat / 86400 saniyedir)ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
26:33:21.68
paste
benim en sevdiğim komut 8-)
Kabul edilen cevabı iptal etmek ve klasik UNIX ters parlatma aracını kullanmak:
{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
-show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc
783.493000
Yani: Eklemek +
ve p
sonra onu boruya sokmak dc
, toplamı elde etmek.
$ 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'ın kurulu olduğundan emin olun .
Ubuntu olarak ffmpeg yerine libav gemisi:
#!/bin/sh
for f in *.mp4; do
avprobe -v quiet -show_format_entry duration "$f"
done | paste -sd+ | bc
Ağır MvG fikirlerine dayalı
Eh, tüm bu çözümler biraz işe ihtiyaç duyuyor, yaptığım şey çok basitti, 1)
İstediğiniz klasöre gidip sağ tıklayın -> diğer uygulamalarla açın
Ardından VLC media player'ı seçin.
işte örnek
Araç çubuğunun hemen altında görebilirsiniz, Oynatma Listesi [10:35:51] yazılı, bu nedenle klasörde 10 saat 35 dakika ve 51 saniye toplam video süresi var