Subtract two time codes

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
0
down vote

favorite












I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:



**Input:**
echo $arr3[0]
echo $arr3[1]

**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790


In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into arrayand 00:00:27.790 - 00:00:24.070 = output into the same array It needs to be in the same format so can use it in FFMPEG.



I also need the first timecode of each array entry, so:



00:00:22.180 
00:00:24.070


in another array so I can use these inputs in ffmpeg as well.



I have no clue as in how I can do this.
Thanks for your help in advance.



EDIT:



I'll use the data as follows



time=$(The first timecode of the array)
duration=$(Timecodes subtracted)

ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4






share|improve this question






















  • I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
    – Jeff Schaller
    Feb 26 at 16:27










  • The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
    – symcbean
    Feb 26 at 17:30






  • 1




    @symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
    – Fiximan
    Feb 26 at 17:51










  • @Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
    – symcbean
    Feb 26 at 21:07











  • @symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
    – Fiximan
    Feb 26 at 22:19














up vote
0
down vote

favorite












I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:



**Input:**
echo $arr3[0]
echo $arr3[1]

**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790


In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into arrayand 00:00:27.790 - 00:00:24.070 = output into the same array It needs to be in the same format so can use it in FFMPEG.



I also need the first timecode of each array entry, so:



00:00:22.180 
00:00:24.070


in another array so I can use these inputs in ffmpeg as well.



I have no clue as in how I can do this.
Thanks for your help in advance.



EDIT:



I'll use the data as follows



time=$(The first timecode of the array)
duration=$(Timecodes subtracted)

ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4






share|improve this question






















  • I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
    – Jeff Schaller
    Feb 26 at 16:27










  • The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
    – symcbean
    Feb 26 at 17:30






  • 1




    @symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
    – Fiximan
    Feb 26 at 17:51










  • @Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
    – symcbean
    Feb 26 at 21:07











  • @symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
    – Fiximan
    Feb 26 at 22:19












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:



**Input:**
echo $arr3[0]
echo $arr3[1]

**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790


In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into arrayand 00:00:27.790 - 00:00:24.070 = output into the same array It needs to be in the same format so can use it in FFMPEG.



I also need the first timecode of each array entry, so:



00:00:22.180 
00:00:24.070


in another array so I can use these inputs in ffmpeg as well.



I have no clue as in how I can do this.
Thanks for your help in advance.



EDIT:



I'll use the data as follows



time=$(The first timecode of the array)
duration=$(Timecodes subtracted)

ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4






share|improve this question














I need to subtract two time codes from each other, I have multiple in an array and the output looks like this:



**Input:**
echo $arr3[0]
echo $arr3[1]

**Output:**
00:00:22.180 --> 00:00:25.600
00:00:24.070 --> 00:00:27.790


In this example the following equation needs to take place 00:00:25.600 - 00:00:22.180 = output into arrayand 00:00:27.790 - 00:00:24.070 = output into the same array It needs to be in the same format so can use it in FFMPEG.



I also need the first timecode of each array entry, so:



00:00:22.180 
00:00:24.070


in another array so I can use these inputs in ffmpeg as well.



I have no clue as in how I can do this.
Thanks for your help in advance.



EDIT:



I'll use the data as follows



time=$(The first timecode of the array)
duration=$(Timecodes subtracted)

ffmpeg -i movie.mp4 -ss $time -t $duration -async 1 cut.mp4








share|improve this question













share|improve this question




share|improve this question








edited Feb 26 at 16:32

























asked Feb 26 at 16:14









tjallo

176




176











  • I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
    – Jeff Schaller
    Feb 26 at 16:27










  • The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
    – symcbean
    Feb 26 at 17:30






  • 1




    @symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
    – Fiximan
    Feb 26 at 17:51










  • @Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
    – symcbean
    Feb 26 at 21:07











  • @symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
    – Fiximan
    Feb 26 at 22:19
















  • I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
    – Jeff Schaller
    Feb 26 at 16:27










  • The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
    – symcbean
    Feb 26 at 17:30






  • 1




    @symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
    – Fiximan
    Feb 26 at 17:51










  • @Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
    – symcbean
    Feb 26 at 21:07











  • @symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
    – Fiximan
    Feb 26 at 22:19















I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
– Jeff Schaller
Feb 26 at 16:27




I think you should spell out a bit more what data is going into what arrays. If you have arr3 with some timestamp/string data, where should the differences go? Into the same array & position, or a new array? Where should the first timecode data go? If you show how you'll use them, you'll get more useful answers.
– Jeff Schaller
Feb 26 at 16:27












The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
– symcbean
Feb 26 at 17:30




The default time utilities exposed in the shell only work with 1 second level granularity. You're going to have to write your own parser/generator from scratch.
– symcbean
Feb 26 at 17:30




1




1




@symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
– Fiximan
Feb 26 at 17:51




@symcbean date (GNU coreutils) 8.25 allows nanosecond accuracy.
– Fiximan
Feb 26 at 17:51












@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
– symcbean
Feb 26 at 21:07





@Fiximan: I stand corrected, and I see you can specify the OUPUT format with nanosecond precision, but how do you convert an input string with fractional seconds into a numeric value?
– symcbean
Feb 26 at 21:07













@symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
– Fiximan
Feb 26 at 22:19




@symcbean See my answer below - I found no entry in info regarding a nanosecond time -> human readable conversion, thus relied on bash integer arithmetic and separated treatment of epoch time and fractional seconds. It's dangerous though, as e.g. discussed here nanoseconds seem to be a GNU-extension not present in BSD-Unices.
– Fiximan
Feb 26 at 22:19










2 Answers
2






active

oldest

votes

















up vote
1
down vote



accepted










Given an array arr3 that contains sample data:



declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
[1]="00:00:24.070 --> 00:00:27.790")


You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.



# 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 "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
done


The codes2seconds function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc for the conversion into total number of seconds.



The seconds2codes function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.



The subtracttimes function converts the two parameters to fractional seconds then asks bc for their difference.



The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg call to match your sample output.



Results:



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





share|improve this answer



























    up vote
    1
    down vote













    Well, for time codes date usually pops into my mind. Not the most elegant script, but it does the job...



    I assume from your question, that you have beginning and end times already read into respective arrays and will use start and end as these values here and do it step by step:



    #!/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"


    Result



    bash script.sh
    00:00:01.890


    All in one line



    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 ))"


    Please note that I am not aware if nanosecond time in date is a POSIX standard feature.






    share|improve this answer




















    • Thanks for the solution, worked for me!
      – tjallo
      Feb 26 at 19:11










    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f426724%2fsubtract-two-time-codes%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    Given an array arr3 that contains sample data:



    declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
    [1]="00:00:24.070 --> 00:00:27.790")


    You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.



    # 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 "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
    done


    The codes2seconds function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc for the conversion into total number of seconds.



    The seconds2codes function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.



    The subtracttimes function converts the two parameters to fractional seconds then asks bc for their difference.



    The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg call to match your sample output.



    Results:



    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





    share|improve this answer
























      up vote
      1
      down vote



      accepted










      Given an array arr3 that contains sample data:



      declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
      [1]="00:00:24.070 --> 00:00:27.790")


      You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.



      # 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 "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
      done


      The codes2seconds function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc for the conversion into total number of seconds.



      The seconds2codes function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.



      The subtracttimes function converts the two parameters to fractional seconds then asks bc for their difference.



      The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg call to match your sample output.



      Results:



      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





      share|improve this answer






















        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        Given an array arr3 that contains sample data:



        declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
        [1]="00:00:24.070 --> 00:00:27.790")


        You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.



        # 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 "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
        done


        The codes2seconds function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc for the conversion into total number of seconds.



        The seconds2codes function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.



        The subtracttimes function converts the two parameters to fractional seconds then asks bc for their difference.



        The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg call to match your sample output.



        Results:



        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





        share|improve this answer












        Given an array arr3 that contains sample data:



        declare -a arr3=([0]="00:00:22.180 --> 00:00:25.600"
        [1]="00:00:24.070 --> 00:00:27.790")


        You could loop through each element in the array, strip out the start time and end time, convert them to fractional seconds, compute the duration, then covert that duration back to hh:mm:ss.sss format for the ffmpeg command.



        # 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 "%sn" "ffmpeg -i movie.mp4 -ss $range%% -->* -t $duration -async 1 cut.mp4"
        done


        The codes2seconds function expects input in HH:MM:SS.sss format; it strips out the various elements using parameter expansion then passes them to bc for the conversion into total number of seconds.



        The seconds2codes function expects a fractional number of seconds and reverses the conversion, resulting in an HH:MM:SS.sss string.



        The subtracttimes function converts the two parameters to fractional seconds then asks bc for their difference.



        The loop at the end goes through each element of arr3; it uses the above functions to calculate the duration (again using parameter expansion to retrieve the two times) then prints out a sample ffmpeg call to match your sample output.



        Results:



        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






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 27 at 2:00









        Jeff Schaller

        31.2k846105




        31.2k846105






















            up vote
            1
            down vote













            Well, for time codes date usually pops into my mind. Not the most elegant script, but it does the job...



            I assume from your question, that you have beginning and end times already read into respective arrays and will use start and end as these values here and do it step by step:



            #!/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"


            Result



            bash script.sh
            00:00:01.890


            All in one line



            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 ))"


            Please note that I am not aware if nanosecond time in date is a POSIX standard feature.






            share|improve this answer




















            • Thanks for the solution, worked for me!
              – tjallo
              Feb 26 at 19:11














            up vote
            1
            down vote













            Well, for time codes date usually pops into my mind. Not the most elegant script, but it does the job...



            I assume from your question, that you have beginning and end times already read into respective arrays and will use start and end as these values here and do it step by step:



            #!/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"


            Result



            bash script.sh
            00:00:01.890


            All in one line



            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 ))"


            Please note that I am not aware if nanosecond time in date is a POSIX standard feature.






            share|improve this answer




















            • Thanks for the solution, worked for me!
              – tjallo
              Feb 26 at 19:11












            up vote
            1
            down vote










            up vote
            1
            down vote









            Well, for time codes date usually pops into my mind. Not the most elegant script, but it does the job...



            I assume from your question, that you have beginning and end times already read into respective arrays and will use start and end as these values here and do it step by step:



            #!/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"


            Result



            bash script.sh
            00:00:01.890


            All in one line



            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 ))"


            Please note that I am not aware if nanosecond time in date is a POSIX standard feature.






            share|improve this answer












            Well, for time codes date usually pops into my mind. Not the most elegant script, but it does the job...



            I assume from your question, that you have beginning and end times already read into respective arrays and will use start and end as these values here and do it step by step:



            #!/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"


            Result



            bash script.sh
            00:00:01.890


            All in one line



            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 ))"


            Please note that I am not aware if nanosecond time in date is a POSIX standard feature.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Feb 26 at 17:40









            Fiximan

            2,941422




            2,941422











            • Thanks for the solution, worked for me!
              – tjallo
              Feb 26 at 19:11
















            • Thanks for the solution, worked for me!
              – tjallo
              Feb 26 at 19:11















            Thanks for the solution, worked for me!
            – tjallo
            Feb 26 at 19:11




            Thanks for the solution, worked for me!
            – tjallo
            Feb 26 at 19:11












             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f426724%2fsubtract-two-time-codes%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay