シェル スクリプトで数値を時刻形式に変換するにはどうすればよいでしょうか?

シェル スクリプトで数値を時刻形式に変換するにはどうすればよいでしょうか?

動画をこのように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;

ただし、期間が 1 時間未満の場合にのみ機能します。 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 時間に設定しています。この場合の整数は 10 分単位の時間です (BASH 組み込み計算機によって計算されます: $((...)))。

記号は、結果を表示するための形式を指定することを+示しますdate。この場合、時間 ( %H) と分 ( %M) のみを気にします。

そして最後に、 は-uローカル時間ではなく UTC 時間として表示します。 この場合、UNIX 時間を指定したときに時間を UTC として指定したため、これは重要です (UNIX 時間は常に UTC です)。 を指定しないと、数字が 0 から始まらない可能性が高くなります-u

BASH 変数置換の説明

このdateコマンドはまさに必要なものを提供してくれました。しかし、ファイル名にコロンが含まれていると問題が発生するか、標準ではない可能性があります。そのため、':' を '-' に置き換えます。これは or コマンドで実行できますsedが、これは非常に簡単なタスクなので、BASH で実行できるのになぜ新しいサブシェルを生成するのでしょうかcuttr

ここでは、BASH の単純な式置換を使用します。これを行うには、変数を中括弧 ( ${hrmin}) で囲み、標準のスラッシュ表記を使用する必要があります。最初のスラッシュの後の最初の文字列は検索パターンです。2 番目のスラッシュの後の 2 番目の文字列は置換です。

BASHの変数置換などについては、http://tldp.org/LDP/abs/html/パラメータ置換.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 はタイムスタンプ形式として [HH:MM:SS] だけでなく単純な秒も受け入れることがわかりました。

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;

関連情報