Can I run an external audio player program from Julia? Or simply playback a sterio .wav file?

I am trying to play a wav file (in stereo) with my sound card (Windows 10), and haven’t been able to work it so far.

WAV.jl doesn’t support playback in Windows, and I can’t seem to work out how to get it working in PortAudio.jl either. It is surprisingly difficult to play back a two channel (stereo) wav file in Julia so far.

So I have decided to use the run command to play VLC player and point it to a file. I can’t even get the run(vlc.exe) to work either, not sure if I am in the wrong directory or not…

cd(dirname(@__FILE__))

run(`calc.exe`) # works fine

run(`vlc.exe`)
ERROR: failed process: Process(`vlc.exe`, ProcessExited(3221225781)) [3221225781]

Stacktrace:
 [1] pipeline_error at .\process.jl:525 [inlined]
 [2] run(::Cmd; wait::Bool) at .\process.jl:440
 [3] run(::Cmd) at .\process.jl:438
 [4] top-level scope at REPL[25]:100: 

I put a copy of vlc.exe in the local directory. Note that calc.exe works, so I presume I am working in the wrong directory? If I place my vlc.exe and WaveFile.wav in the “correct” directory, should it work? Or better still, how can I make it work for any directory I choose?

Strangely enough when I do the following:

cd(dirname(@__FILE__))

path = "D:/Documents/OneDrive/WaveFile.wav"

Threads.@spawn run(`vlc $path`)

julia> Threads.@spawn run(`vlc $path`)
Task (runnable) @0x00000000146dc5d0

It says “runnable”, but still no sound comes out. So I really don’t understand where these files need to be, nor why it says it should run but still nothing comes out from my speakers.

I simply want to play .wav files from my sound card, with plans to get this working in a GUI later. I’d be grateful if anyone is able to play stereo though their sound card successfully and could provide a working example.

1 Like

Try:

run(`"""C:\Program Files (x86)\VideoLAN\VLC\vlc.exe"""`)

That should start VLC. You might need to change the path if you installed it somewhere else.

To pass it the wav file do:

path = "D:\\Documents\\OneDrive\\WaveFile.wav"
run(`"""C:\Program Files (x86)\VideoLAN\VLC\vlc.exe""" $path`)
2 Likes

Thank you, that solved the problem. I am very grateful!

I noticed that when you execute it, while the vlc window is open, Julia is busy “evaluating”, and you cannot send a second run command until you close the vlc window.

Is there a run command to exit or close the vlc window, so I can sequence the next wav file to play?

You can use @async run(…) If you don’t want to keep the repl busy

1 Like

I would use one of the following:

  1. Ask VLC to exit when finished, and let Julia wait until the command is finished (as you already do):

    run(`vlc --play-and-exit $file`)
    
  2. Play the different files with the same VLC instance, and tell Julia to not wait for VLC to exit. To play the first file, use

    p = run(`vlc --one-instance $file`, wait=false)
    

    This will let our long-running process work in the background. Then for subsequent files, do

    run(`vlc --one-instance $file`)
    

    This will play the file using the same instance as before (the VLC instance we start here will transfer the play command to the long-running instance and exit immediately, so it makes sense to wait on that, so we don’t add wait=false). When you’re done with all the files, do

    kill(p)
    

    This will ask the long running instance to terminate.

3 Likes

Thanks for this, it works great! I found the best option is the --play-and-exit option because if I try to put the kill( p ) in the same script, it kills the process before the first file has even completed playing:

path = "D:\\Documents\\OneDrive\\WaveFile.wav"

p = run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --one-instance $path`, wait=false)
run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --one-instance $path`)
run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --one-instance $path`)
run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --one-instance $path`)
kill(p)

Where as --play-and-exit- works great because it opens and closes each session after playing each file:


run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --play-and-exit $path`) 
run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --play-and-exit $path`) 
run(`"""C:\Program Files\VideoLAN\VLC\vlc.exe""" --play-and-exit $path`) 

Thanks for your help!

1 Like