User-defined tag to calculate audio file duration in milliseconds?

Started by Wally, August 08, 2017, 12:38:56 PM

Previous topic - Next topic

Wally

I'm using ExifTool to batch-process sets of audio files. Using the -p option with a custom .fmt file I'm generating a custom implementation doc for incorporating the audio files into a game. For much of my requirements, it's working great.

However, part of my doc requires including the duration of each audio file in milliseconds. The 'Duration' tag returns a value in decimal format, but appears to be slightly inaccurate. For an audio file that my editor says is 1974 milliseconds long, Exiftool is returning 2.04s.

Aside from that, there is still a way I have in mind to get duration in milliseconds. Another part of our implementation requires the inclusion of markers (or 'TracksMarkersName' in ExifTool tag name lingo). With a marker placed at the very end of the audio file I can get the precise duration in samples. Dividing that value by the file's sample rate will give me the millisecond value I need.

So what I'm after is a user-defined tag that can take the last TracksMarkersStartTime value (as the last indexed list-item of a TracksMarkersStartTime tag) and divide it by the SampleRate tag value.

Is this possible? I'm already using the Example.config file to get access to the BaseName custom tag, but coding my own tags is a bit beyond my paygrade.  ;)

Any assistance with this would be greatly appreciated!

Phil Harvey

Try this in the Composite tags section of the config file:

        MyDuration => {
            Require => {
                0 => 'TracksMarkersStartTime',
                1 => 'SampleRate',
            },
            ValueConv => '$val[0] / $val[1]',
        },


(Unless the Duration exists in the metadata, ExifTool's Composite Duration calculation is only approximate since it doesn't parse the audio stream.)

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Wally

Wow, thanks for such a fast reply, I'll give it a try right now. :)

Wally

Hmm, the returned value was a massive number, way out of range. It may be summing all the values in the TracksMarkersStartTime list. Is there a way to specify the last value in the TracksMarkersStartTime value list in the Composite tag code?

Phil Harvey

Oh.  TracksMarkersStartTime is a list?

Try this then:

        MyDuration => {
            Require => {
                0 => 'TracksMarkersStartTime',
                1 => 'SampleRate',
            },
            ValueConv => '(ref $val[0] eq "ARRAY" ? $val[0][-1] : $val[0]) / $val[1]',
        },


If this doesn't work, show me the output of this command and I can figure it out:

exiftool -TracksMarkersStartTime -SampleRate -sep '.' -n FILE

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Wally

Worked beautifully, thank you for the rapid-fire solutions, Phil!

OK, one last ask (for now)  ;)

Is it possible to return a rounded value converted to milliseconds? The file I just tried it on returned 10.8674376417234 but if I could get it to be '10867' that would be perfect.

Thanks again!

Phil Harvey

Great!  Use this to return nearest integer ms:

        MyDuration => {
            Require => {
                0 => 'TracksMarkersStartTime',
                1 => 'SampleRate',
            },
            ValueConv => '(ref $val[0] eq "ARRAY" ? $val[0][-1] : $val[0]) / $val[1]',
            PrintConv => 'int($val * 1000 + 0.5)',
        },


The 0.5 is added to round to the nearest ms.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

Wally