.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リポジトリにはありません(それはと競合するため、馬鹿げていますffmpeg
)ので、ATMを試すことはできませんが、次のように実行するとファイルの期間がわかりますavprobe -show_format_entry duration myfile.mp4
かavprobe -loglevel quiet -show_format_entry duration myfile.mp4
?これらのコマンドのいずれかを使用すると、ファイルの継続時間とともに1行の出力が得られるはずです。わからない。
これにより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です。秒の後のコンマはmyを気にしませんawk
が、問題がある場合は、とのtr -d ,
間のパイプラインにを含めることができます。ffmpeg
awk
今、slmからの部分が来ます:私はpaste
改行をプラス記号に置き換えるために使用していますが、末尾の改行には影響しません(この回答の前のバージョンでtr \\n +
持っていたのとは反対です)。それはに与えることができる合計式を与えます。bc
date
時間のような形式を処理するために使用するというslmのアイデアに触発され、ここでは結果の秒を小数部で日、時間、分、秒としてフォーマットするバージョンを使用します。
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]*$//'
中の部分 $(…)
は以前とまったく同じです。使用して@
1970年1月1日以降指標として文字を、私たちは秒数としてこれを使用して得られた「日付」は今年、時間とナノ秒の日としてフォーマットされます。その年の日から1を減算します。ゼロ秒の入力はすでにその年の1970年の1日目につながっているためです。年の日数をゼロから開始する方法はないと思います。
最後sed
は余分な末尾のゼロを取り除きます。このTZ
設定により、UTCが強制的に使用されるようになります。これにより、サマータイムが非常に大きなビデオコレクションに干渉することはありません。ただし、1年以上のビデオがある場合、このアプローチはまだ機能しません。
私は.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
(、/ 86400秒の持続時間≥24時間です)
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がインストールされていることを確認してください。
さて、これらのすべてのソリューションには少し作業が必要です。
目的のフォルダに移動し、右クリック->他のアプリケーションで開く
次に、VLCメディアプレーヤーを選択し、
ここに例があります
ツールバーのすぐ下に、プレイリスト[10:35:51]と書かれているので、フォルダーには合計10時間35分51秒間のビデオが含まれています