Saya punya daftar .tsfile:
out1.ts ... out749.ts out8159.ts out8818.ts
Bagaimana saya bisa mendapatkan total durasi (waktu berjalan) dari semua file ini?
Saya punya daftar .tsfile:
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 .tssini 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 .mp4file 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 pasteuntuk meneruskan output ke bcdan 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 .tsfile 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 .mp4file 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 exiftoolinternal ConvertDurationuntuk itu (Anda memerlukan versi yang relatif baru):
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)
}' ./*.mp4| tail -n1
0:09:15
ffprobesebelumnya.
pastedan bc! jauh lebih bersih daripada dengan awkkatakanlah.
bcakan melakukan presisi yang sewenang-wenang, satu kelemahannya adalah apakah ...| paste -sd+ - | bcakan mencapai batas ukuran garis di beberapa bcimplementasi (misalnya seq 429 | paste -sd+ - | bcgagal dengan OpenSolaris bc) atau memiliki potensi untuk menggunakan semua memori pada yang lain.
avprobedi 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.mp4atau 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 ffmpegdan 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' | bcmemperluas masing-masing argumen dan mengganti spasi dan menyalurkannya ke bckalkulator linux yang umum
Merampingkan jawaban @ jmunsch , dan menggunakan pasteSaya 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 ffmpeguntuk mencetak durasinya, mengabaikan kesalahan tentang file output yang hilang dan mencari output error untuk garis durasi. Saya memohon ffmpegdengan semua aspek lokal yang dipaksa ke lokal C standar, sehingga saya tidak perlu khawatir tentang pesan output lokal.
Selanjutnya saya menggunakan satu awkbukan miliknya grep | grep | head | tr | awk. Itu awkdoa 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 ffmpegdan awk.
Sekarang bagian dari slm: Saya menggunakan pasteuntuk 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 dateuntuk 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 sedmenyingkirkan nol tambahan trailing. The TZPengaturan 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 .tsekstensi, tetapi dengan asumsi mereka adalah beberapa jenis file video yang dapat Anda gunakan ffmpeguntuk 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.mp4dan 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 dateperintah kemudian digunakan untuk menghitung jumlah detik sinus zaman Unix (1970/01/01). Inilah dateperintah di atas yang pecah sehingga lebih mudah dilihat:
$ date -ud "1970/01/01 00:23:17.01" +%s
1397
CATATAN: Menggunakan datecara 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 forloop kita dan menjalankannya menjadi pasteperintah 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, bcuntuk 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.
datetercekik jika ffmpeg -i some.mp4 2>&1 | grep -oP "(?<=Duration: ).*(?=, start.*)"mengembalikan sesuatu seperti 26:33:21.68(yaitu, durasi ≥ 24 jam / 86400 detik)
pasteadalah 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 pkemudian memasukkannya ke dalam dcdan 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