Привет, Хабр! Недавно ясел смотреть «марафон лекций», а через пару часов понял: я понятия не имею, сколько ещё впереди. Час? Десять? А может, это вообще сериал длиной в жизнь? Вот так родился mdur — утилита, которая считает, сколько часов, минут и секунд тебе предстоит потратить на медиафайлы. Без преувеличений.

Зачем это нужно?

Представьте: вы скачали кучу лекций, подкастов, фильмов, музыки, а теперь хотите понять, сколько времени вам предстоит «потерять». Или, может, вы архивируете медиа и хотите проверить, не упустили ли что‑то важное. Или... вы просто одержимый метриками человек (как я). В любом случае, mdur — это ваш цифровой хронометрист.

Что он умеет? (И как это использовать)

mdur — это консольная утилита на Bash, которая анализирует длительность ваших медиафайлов (видео и аудио) и выдает результат в удобочитаемом формате. Да, я знаю, что есть ffmpeg и ffprobe, но кому охота вручную складывать часы и минуты из 200 файлов? (или каждый раз писать большой кусок кода)

Базовое использование

Запускаете в терминале:

mdur

И получаете:

Общая длительность: 12:34:56
Файлов: 42

Вот и всё. Никаких сложностей. Просто переходите в нужную папку и запускаете. Хотите проверить домашнюю папку с видео?

mdur ~/Videos

Расширенные возможности

Вот что еще можно:

Только текущая папка (без рекурсии):

mdur -r

Потому что иногда вы действительно не хотите копаться в подпапках, которые создали три года назад и до сих пор боялись открыть.

Сортировка по длительности (самые длинные вверху):

mdur -s d

Полезно, когда нужно понять, какой файл «съел» больше всего времени.

Только определенные ваши форматы (например, MP4 и MOV):

mdur -t mp4,mov

Показать формат файлов в выводе:

mdur -f

Тогда вывод будет выглядеть вот так:

Длительность   Формат  Имя файла
--------------------------------
02:15:33      mp4     lecture_1.mp4
76:22:08      mov     Winx_Club.mov
...

Подробный вывод с прогрессом:

mdur -v

Когда вы запускаете анализ на 500 ГБ видео и хотите знать, что скрипт еще жив.

Поддерживает всё, что можно назвать медиа — от MP4 до FLAC. Полный список — в README или исходниках, но, скорее всего, твой формат уже там.

Установка: Одна команда и вуаля

curl -sSL https://raw.githubusercontent.com/BOMUND/mdur/main/install.sh | sudo bash

Требуется только ffmpeg (для ffprobe) и Bash 4.0+. На большинстве современных систем это уже есть. Если нет — установите через пакетный менеджер, как указано в выводе ошибки (да, я позаботился о том, чтобы подсказать, как починить).

Как это работает?

Скажу честно: когда я начинал писать этот скрипт, я думал, что это будет пара строчек на Python. Но потом вспомнил, что не все пользователи имеют Python (да и не везде запустится), а Bash — есть везде, да и удобнее сделать можно. И начал ковыряться в документации find и ffprobe. (Хотя, можно сказать, и с Bash как в первой готовился)

Самый сложный момент — корректно обработать все возможные ошибки. Например, когда ffprobe возвращает не число, а какой‑то бред (спасибо поврежденным файлам). Вот этот кусок кода:

duration=$(ffprobe -v error -show_entries format=duration -of default=nw=1:nk=1 "$file" 2>/dev/null)
if [ -z "$duration" ]; then
    if $VERBOSE; then
        echo "  Ошибка: не удалось получить длительность для $file" >&2
    fi
    ((errors++))
    continue
fi

Я потратил целый вечер, пытаясь понять, почему скрипт внезапно «замирал». Оказалось, нужно было правильно обработать нулевой вывод ffprobe. Как же я радовался, когда наконец увидел, что ошибки перестали сыпаться!

А еще пришлось разбираться с сортировкой. Хочешь отсортировать по длительности? Нужно сохранить временный файл, потому что в Bash нет встроенной сортировки по числовому значению в середине строки. Вот эта строчка:

sort_cmd="sort -t$'\t' -k1nr"

Полчаса убил на то, чтобы понять, что -k1nr означает «сортировать по первому полю, численно, в обратном порядке». Но когда заработало — был счастлив как ребенок.

И конечно, мой самый гениальный кусок кода всех времен — функция преобразования секунд в ЧЧ:ММ:СС. Вот она:

seconds_to_hms() {
    local seconds=$1
    local hours=$((seconds / 3600))
    local minutes=$(( (seconds % 3600) / 60 ))
    local secs=$((seconds % 60))
    printf "%02d:%02d:%02d" "$hours" "$minutes" "$secs"
}

Просто, элегантно, и главное — работает. Хотя сначала я пробовал делать это через костыли (было по‑красивше), пока не понял, что это дико неэффективно.

Заключение

Если вы когда‑либо задавались вопросом «сколько всего времени я потрачу на эти файлы?», mdur — ваш друг. Он легкий, быстрый, не требует установки кучи зависимостей и сразу дает ответ.
Это мой первый проект и я им часто пользуюсь, мне это самое главное. Рад буду критике, но и от капельки похвалы не откажусь. Ведь других подобных мне «доделанных» определителей общей длительности нет.

Я написал его для себя, но решил поделиться, потому что, возможно, кому‑то еще пригодится. Код открыт, можно форкать, править, улучшать. Если найдете баг — пишите в issues, я постараюсь починить.

Установить можно одной командой (см. выше), исходники — на GitHub. И да, если вдруг заметите, что общая длительность ваших просмотренных медиафайлов превышает 200 часов — возможно, пора сделать перерыв, выйти на улицу и потрогать траву. Скрипт не виноват!

Комментарии (25)