Saya punya daftar .ts
file:
out1.ts ... out749.ts out8159.ts out8818.ts
Bagaimana saya bisa mendapatkan total durasi (waktu berjalan) dari semua file ini?
Saya punya daftar .ts
file:
out1.ts ... out749.ts out8159.ts out8818.ts
Bagaimana saya bisa mendapatkan total durasi (waktu berjalan) dari semua file ini?
Jawaban:
Saya tidak punya di .ts
sini tetapi ini berfungsi untuk .mp4
. Gunakan ffprobe
(bagian dari ffmpeg
) untuk mendapatkan waktu dalam detik, misalnya:
ffprobe -v quiet -of csv=p=0 -show_entries format=duration Inception.mp4
275.690000
jadi untuk semua .mp4
file dalam direktori saat ini:
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \;
149.233333
130.146667
275.690000
lalu gunakan paste
untuk meneruskan output ke bc
dan mendapatkan total waktu dalam detik:
find . -maxdepth 1 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
555.070000
Jadi, untuk .ts
file Anda dapat mencoba:
find . -maxdepth 1 -iname '*.ts' -exec ffprobe -v quiet -of csv=p=0 -show_entries format=duration {} \; | paste -sd+ -| bc
Alat lain yang berfungsi untuk file video yang saya miliki di sini adalah exiftool
, misalnya:
exiftool -S -n Inception.mp4 | grep ^Duration
Duration: 275.69
exiftool -q -p '$Duration#' Inception.mp4
275.69
Total panjang untuk semua .mp4
file di direktori saat ini:
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
Anda juga dapat menyalurkan output ke perintah lain untuk mengonversi total menjadi DD:HH:MM:SS
, lihat jawaban di sini .
Atau gunakan exiftool
internal ConvertDuration
untuk itu (Anda memerlukan versi yang relatif baru):
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
}' ./*.mp4| tail -n1
0:09:15
ffprobe
sebelumnya.
paste
dan bc
! jauh lebih bersih daripada dengan awk
katakanlah.
bc
akan melakukan presisi yang sewenang-wenang, satu kelemahannya adalah apakah ...| paste -sd+ - | bc
akan mencapai batas ukuran garis di beberapa bc
implementasi (misalnya seq 429 | paste -sd+ - | bc
gagal dengan OpenSolaris bc
) atau memiliki potensi untuk menggunakan semua memori pada yang lain.
avprobe
di Arch repo (prolly karena bertentangan dengan ffmpeg
) jadi tidak bisa mencobanya ATM tetapi apakah itu memberi Anda durasi file jika Anda menjalankannya seperti ini: avprobe -show_format_entry duration myfile.mp4
atau avprobe -loglevel quiet -show_format_entry duration myfile.mp4
? Saya pikir salah satu dari perintah ini harus memberi Anda satu baris output dengan durasi file. Namun tidak yakin.
Ini menggunakan ffmpeg
dan mencetak waktu habis dalam total detik:
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
Penjelasan:
for f in *.ts; do
iterates setiap file yang berakhiran ".ts"
ffmpeg -i "$f" 2>&1
pengalihan output ke stderr
grep "Duration" | grep -o " [0-9:.]*, " | head -n1 | tr ',' ' '
mengisolasi waktu
awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }'
Mengubah waktu menjadi detik
times+=("$_t")
menambahkan detik ke array
echo "${times[@]}" | sed 's/ /+/g' | bc
memperluas masing-masing argumen dan mengganti spasi dan menyalurkannya ke bc
kalkulator linux yang umum
Merampingkan jawaban @ jmunsch , dan menggunakan paste
Saya baru belajar dari jawaban @ slm , Anda bisa berakhir dengan sesuatu seperti 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
Seperti yang dilakukan jmunsch, saya menggunakan ffmpeg
untuk mencetak durasinya, mengabaikan kesalahan tentang file output yang hilang dan mencari output error untuk garis durasi. Saya memohon ffmpeg
dengan semua aspek lokal yang dipaksa ke lokal C standar, sehingga saya tidak perlu khawatir tentang pesan output lokal.
Selanjutnya saya menggunakan satu awk
bukan miliknya grep | grep | head | tr | awk
. Itu awk
doa mencari garis (mudah-mudahan unik) mengandung Duration:
. Menggunakan titik dua sebagai pemisah, label itu adalah bidang 1, jamnya adalah bidang 2, menit yang diajukan 3 dan bidang detik 4. Tanda koma setelah detik tampaknya tidak mengganggu saya awk
, tetapi jika seseorang memiliki masalah di sana, ia dapat termasuk tr -d ,
dalam jalur pipa antara ffmpeg
dan awk
.
Sekarang bagian dari slm: Saya menggunakan paste
untuk mengganti baris baru dengan tanda tambah, tetapi tanpa mempengaruhi baris baru (bertentangan dengan yang tr \\n +
saya miliki di versi sebelumnya dari jawaban ini). Itu memberikan ekspresi jumlah yang dapat diumpankan bc
.
Terinspirasi oleh ide slm tentang penggunaan date
untuk menangani format seperti waktu, berikut adalah versi yang menggunakannya untuk memformat detik yang dihasilkan sebagai hari, jam, menit, dan detik dengan bagian pecahan:
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]*$//'
Bagian dalam $(…)
persis seperti sebelumnya. Menggunakan @
karakter sebagai indikasi, kami menggunakan ini sebagai jumlah detik sejak 1 Januari 1970. "Tanggal" yang dihasilkan akan diformat sebagai hari dalam setahun, waktu dan nanodetik. Sejak hari itu tahun kita mengurangi satu, karena input nol detik sudah mengarah ke hari 1 tahun itu tahun 1970. Saya tidak berpikir ada cara untuk mendapatkan hari dalam hitungan tahun mulai dari nol.
Final sed
menyingkirkan nol tambahan trailing. The TZ
Pengaturan mudah-mudahan harus memaksa penggunaan UTC, sehingga daylight saving time tidak akan mengganggu benar-benar koleksi video besar. Jika Anda memiliki video lebih dari satu tahun, pendekatan ini tetap tidak akan berhasil.
Saya tidak terbiasa dengan .ts
ekstensi, tetapi dengan asumsi mereka adalah beberapa jenis file video yang dapat Anda gunakan ffmpeg
untuk mengidentifikasi durasi file seperti:
$ ffmpeg -i some.mp4 2>&1 | grep Dura
Duration: 00:23:17.01, start: 0.000000, bitrate: 504 kb/s
Kami kemudian dapat membagi output ini ke atas, memilih hanya durasi waktu.
$ ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
00:23:17.01
Jadi sekarang kita hanya perlu cara untuk mengulangi file-file kita dan mengumpulkan nilai durasi ini.
$ 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
CATATAN: Di sini untuk contoh saya hanya menyalin file sampel saya some.mp4
dan menamakannya 1.mp4
, 2.mp4
, dan 3.mp4
.
Cuplikan berikut akan mengambil durasi dari atas dan mengubahnya menjadi detik.
$ 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
Ini mengambil durasi kami dan menempatkannya dalam variabel $dur
,, saat kami menelusuri file. The date
perintah kemudian digunakan untuk menghitung jumlah detik sinus zaman Unix (1970/01/01). Inilah date
perintah di atas yang pecah sehingga lebih mudah dilihat:
$ date -ud "1970/01/01 00:23:17.01" +%s
1397
CATATAN: Menggunakan date
cara ini hanya akan berfungsi jika semua file Anda memiliki durasi yang <24 jam (yaitu 86400 detik). Jika Anda membutuhkan sesuatu yang dapat menangani durasi yang lebih besar, Anda dapat menggunakan ini sebagai alternatif:
sed 's/^/((/; s/:/)*60+/g' | bc
Contoh
$ echo 44:29:36.01 | sed 's/^/((/; s/:/)*60+/g' | bc
160176.01
Kita kemudian dapat mengambil output dari for
loop kita dan menjalankannya menjadi paste
perintah yang akan menggabungkan +
tanda - tanda di antara setiap angka, seperti:
$ 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
Akhirnya kami menjalankan ini ke dalam kalkulator baris perintah, bc
untuk menjumlahkannya:
$ 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
Menghasilkan total durasi semua file, dalam detik. Ini tentu saja dapat dikonversi ke beberapa format lain jika diperlukan.
date
tercekik jika ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"
mengembalikan sesuatu seperti 26:33:21.68
(yaitu, durasi ≥ 24 jam / 86400 detik)
paste
adalah perintah favorit saya 8-)
Keluar dari jawaban yang diterima dan menggunakan alat reverse-polish UNIX klasik:
{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
-show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc
783.493000
Yaitu: Menambah +
dan p
kemudian memasukkannya ke dalam dc
dan Anda akan mendapatkan jumlah Anda.
$ 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'
Pastikan Anda telah menginstal MPlayer .
Sebagai libav ubuntu, bukan ffmpeg:
#!/bin/sh
for f in *.mp4; do
avprobe -v quiet -show_format_entry duration "$f"
done | paste -sd+ | bc
Sangat didasarkan pada ide-ide MvG
Nah, semua solusi ini perlu sedikit usaha, apa yang saya lakukan sangat sederhana, 1)
pergi ke folder yang diinginkan dan klik kanan -> buka dengan aplikasi lain
Kemudian pilih VLC media player,
di sini adalah contoh
Anda dapat melihat tepat di bawah bilah alat, ada Playlist [10:35:51] tertulis, sehingga folder berisi 10 jam 35 menit dan durasi total video 51 detik