2011-03-04 99 views
1

我想知道如何計算幀中兩個視頻時間碼之間的差異(在這種情況下,第二個等於30幀)。假設點A是600(00:00:02),點B是120(00:00:04)。BASH:如何進行時間碼計算

我該如何計算Pont A和B之間的差異,並使用bash回顯00:00:00.00格式(h:m:s)中的結果?


UPDATE:

這是完美:http://www.1728.com/angle.htm

+1

對於命令行時間碼轉換和算法,你可能想檢出[時間碼程序](https://github.com/sshaw/Time-Timecode#timecode-utility-program)。 – sshaw 2018-02-03 19:31:53

回答

3

首先,export語句是多餘的,因爲當前shell正在擴展$A$B

爲了充分利用時間戳這些數字,GNU date將幫助:

jinx:752 Z$ date -d 00:01:18.44 +%T.%N # to show that it works 
00:01:18.440000000 
jinx:753 Z$ date -d 00:01:18.44 +%s.%N 
1299214878.440000000 

現在你可以做你的計算,然後在最後的顯示轉換回(如埃德溫·巴克說,不要試圖存儲在這種格式中間結果):

jinx:754 Z$ date -d @1299214878.44 +%T.%N 
00:01:18.440000000 
+0

如果輸入時間是幀而不是時間格式,我該如何使用您的建議? (在這種情況下,30幀等於1秒)。 – Roger 2011-03-04 23:41:51

+0

當我讀到原始問題時,你可能會在時間戳中得到它們。如果你以幀數計算它們,那麼你可以忽略輸入轉換步驟,這會給你下一個答案。 – geekosaur 2011-03-05 01:26:55

1

保持所有的時代中「幀」,然後通過一個單一的格式化程序顯示幀的時間。如果您嘗試轉換爲次數,則會使數學轉換更難(因爲時間是基礎系統)。

frames2date() { 
    local secs=$((2 * $1)); 
    date --utc --date "1970-01-01 ${secs} sec" "+%T" 
} 

應該將幀數轉換爲一個時間,請注意,如果您的時間超過24小時,您需要添加年,月和日。

+0

解決了在bash中沒有正確轉義數學的問題。 – 2011-03-04 22:29:06

+0

來調用這個'frames2date $(($ B - $ A))' – 2011-03-04 22:29:51

+0

在這種情況下,時間碼總是低於24小時。 – Roger 2011-03-04 22:54:38

0

(不完美的)解決方案:

隨着我的朋友的幫助下,這是我完整的bash腳本:

#!/bin/bash 

#ffmpeg [inputfile] [starttimecode] [videoduration] [video details] [size] [audio details] [alltherest] [outputfile] 

video=-'vcodec libx264 -vpre slower -crf 22' 
size='-s 320x240' 
audio='-acodec libmp3lame -aq 0 -ac 1' 

in=$(date --utc --date "$3" +%s) 
out=$(date --utc --date "$4" +%s) 
dur=$(date --utc --date "1970-01-01 $[$out-$in] sec" "+%T") 
ss=$(date --utc --date "1970-01-01 $[$in] sec" "+%T") 

ffmpeg -i $1.$2 $video $size $audio -threads 0 -y $1.mp4 

#ffmpeg -i t1.flv -ss 00:00:32 -t 00:00:04 -vcodec libx264 -vpre slower -crf 22 -s 320x240 -acodec libmp3lame -aq 0 -ac 1 -threads 0 -y t1.mp4 

我保存腳本爲「V」這裏就是我把它從CLI:

v t1 flv 00:00:32.658 00:00:36.060 

這樣我可以從CLI的ffmpeg直接切入視頻文件的一部分。但是,時間碼之間的計算是不太準確的,所以我需要工作,它在一點點來實現這一目標:http://www.1728.com/angle.htm

0

這裏是不使用的日期工具的另一種方法:

function timecode_to_int() { 
     if [[ "$1" =~ ^((0*([0-9]+):)?0*([0-9]+):)?0*([0-9]+)(\.([0-9]{1,3}))? ]]; then 
     VALUE=$((${BASH_REMATCH[5]})) 
     [[ -n "${BASH_REMATCH[4]}" ]] && VALUE=$((${BASH_REMATCH[4]}*60+$VALUE)) 
     [[ -n "${BASH_REMATCH[3]}" ]] && VALUE=$((${BASH_REMATCH[3]}*60*60+$VALUE)) 
     VALUE=$(($VALUE*1000)) 

     if [[ -n "${BASH_REMATCH[7]}" ]]; then 
      VALUE=$(($VALUE+10#$(printf %-3s ${BASH_REMATCH[7]} | sed s_\ _0_g))) 
     fi 
     echo "${VALUE}" 
     else 
     echo "Invalid timecode '$1', aborting." >&2 
     exit 1 
     fi 
    } 

    function int_to_timecode() { 
     MILLISECONDS="$(($1%1000))" 
     SECS="$(($1/1000%60))" 
     MINUTES="$(($1/1000/60%60))" 
     HOURS="$(($1/1000/60/60))" 

     if [[ $HOURS -ne 0 ]]; then 
      printf "%d:%02d:%02d" $HOURS $MINUTES $SECS 
     elif [[ $MINUTES -ne 0 ]]; then 
      printf "%d:%02d" $MINUTES $SECS 
     else 
      printf "%d" $SECS 
     fi 
     if [[ ${MILLISECONDS} -ne 0 ]]; then 
      printf ".%03d" $MILLISECONDS | sed s_0*\$__ 
     fi 
    } 

    # To answer your question completely: 
    echo $(int_to_timecode $(($(timecode_to_int "00:00:04")-$(timecode_to_int "00:00:02"))))