Get length of .wav from sox output
Asked Answered
L

9

50

I need to get the length of a .wav file.

Using:

sox output.wav -n stat

Gives:

Samples read:            449718
Length (seconds):     28.107375
Scaled by:         2147483647.0
Maximum amplitude:     0.999969
Minimum amplitude:    -0.999969
Midline amplitude:     0.000000
Mean    norm:          0.145530
Mean    amplitude:     0.000291
RMS     amplitude:     0.249847
Maximum delta:         1.316925
Minimum delta:         0.000000
Mean    delta:         0.033336
RMS     delta:         0.064767
Rough   frequency:          660
Volume adjustment:        1.000

How do I use grep or some other method to only output the value of the length in the second column, i.e. 28.107375?

Thanks

Lunette answered 26/12, 2010 at 15:36 Comment(0)
C
42

The stat effect sends its output to stderr, use 2>&1 to redirect to stdout. Use sed to extract the relevant bits:

sox out.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p'
Childbirth answered 26/12, 2010 at 16:7 Comment(3)
I've got no idea how you constructed this, but it works like a charm. Thank you!Lunette
For what it's worth, using sox v14.0.0 on Windows, the $ (EOL) marker caused this answer to fail to give the result expected (instead of parsing to the end of line, it simply parses till it finds something which isn't a digit or period.Mitchiner
This is more reliable than soxi: this one involves traversing the audio file to calculate the length whereas soxi simply reports what is in the header - regardless of accuracyGaza
A
62

There is a better way:

soxi -D out.wav
Adne answered 25/5, 2011 at 7:0 Comment(7)
Unfortunately it returns wrong duration, distinguish from sox output.wav -n stat method in my case.Ergo
I have never seen it to be wrong - can you distinguish in what situation this is incorrect?Adne
I've cropped the audio with mp3cut.net and got the warn from sox: WARN mp3-util: MAD lost sync with wrong duration. On the other hand sox output.wav -n stat execution returns correct duration in error output thread (see my answer for explanation). Also windows explorer shows correct duration.Ergo
FWIW - I've used this method on linux and mac for years without any such issue - sounds windows specific.Adne
I think the two differ in that soxi uses the header info, while sox looks at the body, too. SO if the header is wrong, the two give different outpu.Altar
@RuprechtvonWaldenfels Interesting theory. Can anyone confirm this? I can't see anything on a quick glance at the man pages.Illusion
Why theory? Man directly states it for soxi (sox --info): "Displays information from the header of a given audio file or files.", for sox stat: "Display time and frequency domain statistical information about the audio. Audio is passed unmodified through the SoX processing chain." You could read further how it statistics collected and calculated also.Act
C
42

The stat effect sends its output to stderr, use 2>&1 to redirect to stdout. Use sed to extract the relevant bits:

sox out.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p'
Childbirth answered 26/12, 2010 at 16:7 Comment(3)
I've got no idea how you constructed this, but it works like a charm. Thank you!Lunette
For what it's worth, using sox v14.0.0 on Windows, the $ (EOL) marker caused this answer to fail to give the result expected (instead of parsing to the end of line, it simply parses till it finds something which isn't a digit or period.Mitchiner
This is more reliable than soxi: this one involves traversing the audio file to calculate the length whereas soxi simply reports what is in the header - regardless of accuracyGaza
G
14

This can be done by using:

  • soxi -D input.mp3 the output will be the duration directly in seconds
  • soxi -d input.mp3 the output will be the duration with the following format hh:mm:ss.ss
Giotto answered 11/11, 2012 at 14:18 Comment(0)
Y
8

This worked for me (in Windows):

sox --i -D out.wav
You answered 11/7, 2012 at 21:25 Comment(2)
Unfortunately it returns wrong duration, distinguish from sox output.wav -n stat method in my case.Ergo
stat returned 139.389388 and this returned 139.407007. For my purposes it's OK. Thanks.Groceries
T
4

I just added an option for JSON output on the 'stat' and 'stats' effects. This should make getting info about an audiofile a little bit easier.

https://github.com/kylophone/SoxJSONStatStats

$ sox somefile.wav -n stat -json
Turboelectric answered 25/4, 2014 at 18:38 Comment(0)
C
2

for ruby:

string = `sox --i -D file_wav 2>&1` 
string.strip.to_f
Cupid answered 11/10, 2018 at 11:3 Comment(0)
E
1

There is my solution for C# (unfortunately sox --i -D out.wav returns wrong result in some cases):

public static double GetAudioDuration(string soxPath, string audioPath)
{
    double duration = 0;
    var startInfo = new ProcessStartInfo(soxPath,
        string.Format("\"{0}\" -n stat", audioPath));
    startInfo.UseShellExecute = false;
    startInfo.CreateNoWindow = true;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    var process = Process.Start(startInfo);
    process.WaitForExit();

    string str;
    using (var outputThread = process.StandardError)
        str = outputThread.ReadToEnd();

    if (string.IsNullOrEmpty(str))
        using (var outputThread = process.StandardOutput)
            str = outputThread.ReadToEnd();

    try
    {
        string[] lines = str.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
        string lengthLine = lines.First(line => line.Contains("Length (seconds)"));
        duration = double.Parse(lengthLine.Split(':')[1]);
    }
    catch (Exception ex)
    {
    }

    return duration;
}
Ergo answered 9/3, 2013 at 19:30 Comment(0)
V
0

In CentOS

sox out.wav -e stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]([0-9.])$#\1#p'

Varistor answered 11/2, 2014 at 11:30 Comment(0)
P
0

sox stat output to array and json encode

        $stats_raw = array();
        exec('sox file.wav -n stat 2>&1', $stats_raw);
        $stats = array();

        foreach($stats_raw as $stat) {
            $word = explode(':', $stat);
            $stats[] = array('name' => trim($word[0]), 'value' => trim($word[1]));
        } 
        echo json_encode($stats);
Political answered 2/6, 2015 at 15:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.