Question

I am trying to write a php script where it will take an uploaded mp3 file and automatically create a copy of it in ogg format. My idea is to use exec() or shell_exec() to run dir2ogg from php. This is my code:

$command = 'dir2ogg /var/www/bais-mordechai-laravel/public/uploads/"'.$filename.'"';
$output = shell_exec($command);

The output that I am getting from this is only the first line of the expected output:

dir2ogg 0.11.8 (2009-08-04), converts audio files into ogg vorbis.

When I run this directly from the command line (as root user) I get the following:

dir2ogg 0.11.8 (2009-08-04), converts audio files into ogg vorbis.

INFO: Converting "/var/www/bais-mordechai-laravel/public/uploads/Track 02.mp3" (using mpg123 as decoder)...
[wav.c:371] warning: Cannot rewind WAV file. File-format isn't fully conform now.
Encoding standard input to 
         "/var/www/bais-mordechai-laravel/public/uploads/Track 02.ogg" 
at quality 3.00
    Encoding [ 0m15s so far] / [wav.c:371] warning: Cannot rewind WAV file. File-format     isn't fully conform now.


Done encoding file "/var/www/bais-mordechai-laravel/public/uploads/Track 02.ogg"

File length:  3m 50.0s
Elapsed time: 0m 15.7s
Rate:         14.6600
Average bitrate: 91.1 kb/s

So it seems that the function is returning before the command is finished executing.

I thought that perhaps the script finished on its own, but there is no ogg file created as I intend.

So my question is how do I get this to work, or how can I go about debugging this?

UPDATE: Using Mehran's advice, here is my stderr output:

Array
(
[stdout] => dir2ogg 0.11.8 (2009-08-04), converts audio files into ogg vorbis.


[stderr] => Traceback (most recent call last):
  File "/usr/bin/dir2ogg", line 673, in <module>
main()
  File "/usr/bin/dir2ogg", line 641, in main
conf = read_opts()
  File "/usr/bin/dir2ogg", line 120, in read_opts
in_path = [prefix for prefix in os.environ['PATH'].split(os.pathsep) if os.path.exists(os.path.join(prefix, command))]
  File "/usr/lib/python2.7/UserDict.py", line 23, in __getitem__
raise KeyError(key)
KeyError: 'PATH'

[return] => 1
)
Was it helpful?

Solution

The reason behind your problem is specific to your system as I can easily run your code and generate the .ogg file. Here's what I get when I run a php file with your code in it:

dir2ogg 0.11.8 (2009-08-04), converts audio files into ogg vorbis.

INFO: Converting "/home/mehran/001.mp3" (using mpg123 as decoder)...

And as I said before the 001.ogg is successfully created. Whatever is going on with your execution is specific to your configuration. The way to debug it is to get and print the stderr of the process. Here's how you can get it (shell_exec and exec functions do not give you that):

<?php
function _pipeExec($cmd, $input = '')
{
    $proc = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
    fwrite($pipes[0], $input);
    fclose($pipes[0]);
    $stdout = stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[2]);
    $rtn = proc_close($proc);
    $result = array(
        'stdout' => $stdout
        , 'stderr' => $stderr
        , 'return' => $rtn
    );
    return $result;
}

$command = 'dir2ogg /home/mehran/"001.mp3"';
$output = _pipeExec($command);
print_r($output);

You can find more information on proc_open here. But the short description is that it does what exactly you want, it gives you all the outputs one process produces. In my computer the above code generates:

Array
(
    [stdout] => dir2ogg 0.11.8 (2009-08-04), converts audio files into ogg vorbis.

INFO: Converting "/home/mehran/001.mp3" (using mpg123 as decoder)...

    [stderr] => [wav.c:371] warning: Cannot rewind WAV file. File-format isn't fully conform now.
Encoding standard input to 
         "/home/mehran/001.ogg" 
at quality 3.00

    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m00s so far] / 
    Encoding [ 0m00s so far] - 
    Encoding [ 0m00s so far] \ 
    Encoding [ 0m00s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m01s so far] \ 
    Encoding [ 0m01s so far] | 
    Encoding [ 0m01s so far] / 
    Encoding [ 0m01s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m02s so far] / 
    Encoding [ 0m02s so far] - 
    Encoding [ 0m02s so far] \ 
    Encoding [ 0m02s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m03s so far] - 
    Encoding [ 0m03s so far] \ 
    Encoding [ 0m03s so far] | 
    Encoding [ 0m03s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m04s so far] / 
    Encoding [ 0m04s so far] - 
    Encoding [ 0m04s so far] \ 
    Encoding [ 0m04s so far] | 
    Encoding [ 0m05s so far] / 
    Encoding [ 0m05s so far] - 
    Encoding [ 0m05s so far] \ 
    Encoding [ 0m05s so far] | 
    Encoding [ 0m05s so far] / [wav.c:371] warning: Cannot rewind WAV file. File-format isn't fully conform now.

    Encoding [ 0m05s so far] - 

Done encoding file "/home/mehran/001.ogg"

    File length:  3m 13.0s
    Elapsed time: 0m 05.1s
    Rate:         37.8620
    Average bitrate: 110.9 kb/s


    [return] => 0
)

You can use the return value to check for the success of the process, and as you can see even the progress indicator is also printed. Nevertheless, you can look into stderr and find what's wrong with your code.

[UPDATE]

Unfortunately, I can not replicate your error. I just tried to do what you are trying to do and faced a problem of my own I thought it's worth sharing. Here's my complete, working code to upload and convert an audio file:

<?php

function _pipeExec($cmd, $input = '')
{
    $proc = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
    fwrite($pipes[0], $input);
    fclose($pipes[0]);
    $stdout = stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[2]);
    $rtn = proc_close($proc);
    $result = array(
        'stdout' => $stdout
        , 'stderr' => $stderr
        , 'return' => $rtn
    );
    return $result;
}
?>

<html>
<body>

<form method="post" action="./ogg.php" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="music" id="file"><br>
    <input type="submit" name="submit" value="Submit">
</form>

<?php
if (isset($_FILES['music'])) {
    $des = $_FILES['music']['tmp_name'] .'.'. pathinfo($_FILES['music']['name'], PATHINFO_EXTENSION);
    rename($_FILES['music']['tmp_name'], $des);
    $command = 'dir2ogg "' . $des . '"';
    $output = _pipeExec($command);
    echo "<div style='height: 500px; overflow: auto;'><pre>";
    print_r($output);
    echo "</pre></div>";
}
?>

</body>
</html>

The part which if you omit will result in a problem is:

$des = $_FILES['music']['tmp_name'] .'.'. pathinfo($_FILES['music']['name'], PATHINFO_EXTENSION);
rename($_FILES['music']['tmp_name'], $des);

This will rename the temporary uploaded file so it will have the same extension as its original filename, i.e. it will append .mp3 to the uploaded file. Without this I couldn't convert the file to an .ogg file.

One more thing regarding your error, make sure that the file you are uploading is compatible with dir2ogg as I have read in some of the posts here and there that some formats are not compatible and thus dir2ogg outputs errors like yours.

In the end, make sure that your file's size does not exceeds your upload size and/or post size limits. A phpinfo() will prompt you your current upload_max_filesize and post_max_size. Perhaps your file is not uploaded at all! You can make sure of your successful file upload by looking into the $_FILES['music']['error'].

That's all I've got!

OTHER TIPS

You can do that like this;

$command = 'dir2ogg /var/www/bais-mordechai-laravel/public/uploads/"'.$filename.'"';
exec ("$command 2>&1", $convert_output, $return_val);
if(preg_match("/Done/i", $convert_output[10])) {
    echo "Convert complete";
} else {
    echo "Conversion error";
    exit;
}

Key points in my point;

  1. 2>&1 redirects command output to console, so it assigned to $convert_output line by line

  2. I have lokked at your output, and result keyword exists on line 10, "Done encoding....". So you can regex find by using keyword "Done" on ine 10

  3. Last thing, you will not get output until conversion finished

You can also check result output by;

var_dump(array($convert_output, $return_val));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top