как преобразовать число в формат времени в скрипте оболочки?

как преобразовать число в формат времени в скрипте оболочки?

Я хочу разрезать видео на 10-минутные части, как это.

ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 01.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 02.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 03.mp4

С forним будет так.

for i in `seq 10`; do ffmpeg -i video.mp4 -ss 00:${i}0:00 -t 00:10:00 -c copy ${i].mp4; done;

Но это работает только если продолжительность меньше часа. Как преобразовать число в формат времени в оболочке bash?

решение1

BASH не так уж плох для этой проблемы. Вам просто нужно использовать очень мощную, но недоиспользуемую dateкоманду.

for i in {1..10}; do
  hrmin=$(date -u -d@$(($i * 10 * 60)) +"%H:%M")
  outfile=${hrmin/:/-}.mp4
  ffmpeg -i video.mp4 -ss ${hrmin}:00 -t 00:10:00 -c copy ${outfile}
done

dateОбъяснение команды

dateс -dфлагами позволяет вам установитькоторыйдата, которую вы хотите отобразить (вместо текущей даты и времени, которые являются значениями по умолчанию). В этом случае я устанавливаю время UNIX, добавляя символ @перед целым числом. Целое число в этом случае — это время с десятиминутными приращениями (вычисляется встроенным калькулятором BASH: $((...))).

Символ +говорит dateо том, что вы хотите указать формат отображения результатов. В нашем случае нас интересуют только часы ( %H) и минуты ( %M).

И наконец, -uis для отображения времени UTC вместо местного. Это важно в данном случае, поскольку мы указали время как UTC, когда дали ему время UNIX (время UNIX всегда как UTC). Числа, скорее всего, не будут начинаться с 0, если вы не укажете -u.

Объяснение замены переменных в BASH

Команда dateдала нам как раз то, что нам было нужно. Но двоеточия в имени файла могут быть проблематичными/нестандартными. Поэтому мы заменяем ':' на '-'. Это можно сделать командой sedили cutили tr, но поскольку это такая простая задача, зачем порождать новую подоболочку, если BASH может это сделать?

Здесь мы используем простую подстановку выражений BASH. Для этого переменная должна быть заключена в фигурные скобки ( ${hrmin}), а затем использована стандартная нотация с косой чертой. Первая строка после первой косой черты — это шаблон поиска. Вторая строка после второй косой черты — это подстановка.

Подстановку переменных BASH и многое другое можно найти на сайтеhttp://tldp.org/LDP/abs/html/parameter-substitution.html.

решение2

Это немного сложнее, но вы можете сделать это в bash достаточно легко. Пример ниже для 2-часового видео, вы можете установить ограничения ( n<=11) соответственно:

k=0; 
i=00;
for ((n=0;n<=11;n++)); do
  if [ $i -ge 60 ]; then 
    let k++; i=00; 
  fi; 
  ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4; 
  let i+=10; 
done

Вы можете увидеть, что это делает, добавив echoк ffmpegстроке:

echo "ffmpeg -i video.mp4 -ss 0$k:$i:00 -t 00:10:00 -c copy $k$i.mp4";

который напечатает:

ffmpeg -i video.mp4 -ss 00:00:00 -t 00:10:00 -c copy 000.mp4
ffmpeg -i video.mp4 -ss 00:10:00 -t 00:10:00 -c copy 010.mp4
ffmpeg -i video.mp4 -ss 00:20:00 -t 00:10:00 -c copy 020.mp4
ffmpeg -i video.mp4 -ss 00:30:00 -t 00:10:00 -c copy 030.mp4
ffmpeg -i video.mp4 -ss 00:40:00 -t 00:10:00 -c copy 040.mp4
ffmpeg -i video.mp4 -ss 00:50:00 -t 00:10:00 -c copy 050.mp4
ffmpeg -i video.mp4 -ss 01:00:00 -t 00:10:00 -c copy 100.mp4
ffmpeg -i video.mp4 -ss 01:10:00 -t 00:10:00 -c copy 110.mp4
ffmpeg -i video.mp4 -ss 01:20:00 -t 00:10:00 -c copy 120.mp4
ffmpeg -i video.mp4 -ss 01:30:00 -t 00:10:00 -c copy 130.mp4
ffmpeg -i video.mp4 -ss 01:40:00 -t 00:10:00 -c copy 140.mp4
ffmpeg -i video.mp4 -ss 01:50:00 -t 00:10:00 -c copy 150.mp4

решение3

Это простая математика: цифра часа — $((i%3600), минут — $((i/60%60)), секунд — $((i%60)). Чтобы добавить начальный ноль там, где это необходимо, простой трюк — добавить 100, а затем удалить начальный 1. Сделайте то же самое с именем файла, если вы хотите избежать начальных нулей.

for i in $(seq 10); do
  minutes=$((i / 60 % 60 + 100)); minutes=${minutes#1}
  seconds=$((i%60)); seconds=${seconds#1}
  i=$((i+100)); i=${i#1}
  ffmpeg -i video.mp4 -ss $((i%3600):$minutes:$seconds -t 00:10:00 -c copy ${i}.mp4
done

решение4

Я обнаружил, что ffmpeg принимает в качестве формата временной метки не только [ЧЧ:ММ:СС], но и простые секунды.

https://trac.ffmpeg.org/wiki/Seeking%20with%20FFmpeg

Поэтому я могу написать вот так.

for i in `seq 10`; do ffmpeg -i video.mp4 -ss $((i*10*60)) -t 00:10:00 -c copy ${i].mp4; done;

Связанный контент