두 개의 타임코드 빼기

두 개의 타임코드 빼기

두 개의 타임코드를 빼야 합니다. 배열에 여러 개의 타임코드가 있으며 출력은 다음과 같습니다.

**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 arrayFFMPEG에서 사용할 수 있도록 동일한 형식이어야 합니다.

또한 각 배열 항목의 첫 번째 타임코드가 필요하므로 다음과 같습니다.

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의 각 요소를 반복합니다. 위 함수를 사용하여 기간을 계산한 다음(다시 매개변수 확장을 사용하여 이를 두 번 검색함) 샘플 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 표준 기능인지 는 알 수 없습니다 .

관련 정보