У мене є список .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файлів у поточному режимі:
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в Arch repos (prolly тому, що це суперечить ffmpeg), тому не можна спробувати його в банкоматі, але він дає вам тривалість файлу, якщо ви запускаєте його так: 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загальному калькулятору Linux
Упорядкуйте відповідь @ 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 року. Отримана "дата" формується як день року, час та наносекунд. З цього дня року ми віднімаємо одне, оскільки введення нульових секунд вже призводить до першого дня 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команда використовується для обчислення кількості секунд, що належать епосі Unix (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:
{ find . -maxdepth 2 -iname '*.mp4' -exec ffprobe -v quiet -of csv=p=0 \
-show_entries format=duration {} \; ; printf '+\n60\n*\np'; } | dc
783.493000
Тобто: Появившись, +а 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 .
Ну, над цим рішенням потрібно трохи попрацювати, що я зробив було дуже просто, 1)
перейшов у потрібну папку і клацніть правою кнопкою миші -> відкрити з іншим додатком
Потім виберіть медіаплеєр VLC,
ось приклад
Ви можете бачити прямо під панеллю інструментів, там написано Плейлист [10:35:51] , тому папка містить 10 годин 35 хвилин та загальну тривалість 51 сек.