
2つのタイムコードを引く必要があります。配列には複数のタイムコードがあり、出力は次のとおりです。
**Input:**
echo ${arr3[0]}
echo ${arr3[1]}
**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790
この例では、次の式を使用し00:00:25.600 - 00:00:22.180 = output into array
、00:00:27.790 - 00:00:24.070 = output into the same array
FFMPEGで使用できるように同じ形式でなければなりません。
また、各配列項目の最初のタイムコードが必要なので、次のようになります。
00:00:22.180
00:00:24.070
ffmpegでも、これらの入力を使用できるように別の配列に保存します。
編集する:
私は次のようにデータを使用します
time=$(The first timecode of the array)
duration=$(Timecodes subtracted)
ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4
答え1
サンプルデータを含む配列arr3が与えられた場合:
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
配列内の各要素を繰り返し、開始時間と終了時間を削除し、小数秒に変換し、期間を計算してから、その期間をffmpegコマンドのhh:mm:ss.sss形式に戻すことができます。
# converts HH:MM:SS.sss to fractional seconds
codes2seconds() (
local hh=${1%%:*}
local rest=${1#*:}
local mm=${rest%%:*}
local ss=${rest#*:}
printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss")
)
# converts fractional seconds to HH:MM:SS.sss
seconds2codes() (
local seconds=$1
local hh=$(bc <<< "scale=0; $seconds / 3600")
local remainder=$(bc <<< "$seconds % 3600")
local mm=$(bc <<< "scale=0; $remainder / 60")
local ss=$(bc <<< "$remainder % 60")
printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss"
)
subtracttimes() (
local t1sec=$(codes2seconds "$1")
local t2sec=$(codes2seconds "$2")
printf "%s" $(bc <<< "$t2sec - $t1sec")
)
declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")
for range in "${arr3[@]}"
do
duration=$(subtracttimes "${range%% -->*}" "${range##*--> }")
printf "%s\n" "ffmpeg -i movie.mp4 -ss ${range%% -->*} -t $duration -async 1 cut.mp4"
done
このcodes2seconds
関数にはHH:MM:SS.sss形式の入力が必要です。引数拡張を使用してさまざまな要素を削除し、それを渡してbc
合計秒に変換します。
このseconds2codes
関数は秒の小数部分を取り、変換を逆にしてHH:MM:SS.sss文字列を生成します。
このsubtracttimes
関数は両方の引数を秒単位で変換し、bc
違いを尋ねます。
最後のループはarr3の各要素を繰り返します。上記の関数を使用して期間を計算し(再度パラメータ拡張を使用してそれを2回取得します)、サンプル出力に一致するサンプルffmpeg
呼び出しを印刷します。
結果:
ffmpeg -i movie.mp4 -ss 00:00:22.180 -t 3.420 -async 1 cut.mp4
ffmpeg -i movie.mp4 -ss 00:00:24.070 -t 3.720 -async 1 cut.mp4
答え2
まあ、普通のタイムコードがdate
思い浮かびます。最もエレガントなスクリプトではありませんが、作業を完了します。
あなたの質問から開始時間と終了時間をそれぞれの配列として読み、ここでその値を使用して段階的に進むとしますstart
。end
#!/bin/bash
start=00:00:22.180
end=00:00:24.070
#convert timestamps to epoch time in nano seconds
start_ns="$(date -u -d"$start" +%s%N)"
end_ns="$(date -u -d"$end" +%s%N)"
difference="$(($end_ns-$start_ns))"
#date does not read epoch time in nanoseconds,
#so it must be converted by division vith 10^9 before display
#date_diff is accurate up to full seconds
#use UTC time (-u) to avoid problems with time zones
date_diff="$( date -u -d@$((difference/1000000000)) +%H:%M:%S )"
#take care of milliseconds as remainder of division by 10^9 and correction by 10^6
ms_diff="$(( $difference%1000000000/1000000 ))"
#combine output to create desired format
echo "$date_diff"."$ms_diff"
結果
bash script.sh
00:00:01.890
すべて連続
echo "$(date -u -d@"$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))/1000000000 ))" +%H:%M:%S)"."$(( ($(date -u -d"$end" +%s%N) - $(date -u -d"$start" +%s%N))%1000000000/1000000 ))"
date
ナノ秒時間がPOSIX標準機能かどうかは不明です。