Can't set volume for vlc player

This forum is about all development around libVLC.
User avatar
Kenemtef
New Cone
New Cone
Posts: 4
Joined: 16 Aug 2023 13:15

Can't set volume for vlc player

Postby Kenemtef » 17 Aug 2023 08:07

Hi. I'm maintaining a java legacy project involving vlc.

For compatibility reasons, we have to do the following:

We place the VLC (almost) entire player in a subdirectory of our project, like this:
Image

And from our java class constructor, we create a ProcessBuilder with the vlc.exe as command, and we create a Process by doing a ProcessBuilder.start().

Then we create a printStream to send commands to vlc, and a BufferedReader to receive whatever vlc logs or prints on console. We also create and start a thread with that process.

While running, we send commands to vlc with in.print() + in.flush(). Examples: «in.print("video.mov\n"); in.flush();» or «in.print("play\n"); in.flush();»

Almost all commands work fine. But the videos we are playing are playing sound at 0 volume. They are not muted, the volume value is zero. You can see in the following capture that the Windows Sound Control of the VLC player does not have the volume icon crossed out, it's just that the volume slider is at the zero step, at the bottom. But the sound, as represented by the little grey bar on the left of the slider, is being played:
Image

The one command that doesn't seem to work is setVolume. We try «in.print("setVolume 100\n"); in.flush();». In the logs we always see an "OK setVolume", but it's always followed by one or two "simple volume changed: 0.000000, muting disabled", maybe not inmediately but less than 100 milliseconds and a few other instructions after the OK.

If we manually move the Windows Sound Slider, the audio volume adjusts accordingly, and in the logs we see one of this messages showing the volume on a per unit basis (example: We put the slider at the top, at the 100 step, we see at the log a "simple volume changed: 1.000000, muting disabled" line; if we put the slider at the 67 step, we see a "simple volume changed: 0.670000, muting disabled" line.

We have tried to send the setVolume command with a non-integer number also, for example «in.print("setVolume 0.5"); in.flush();», but it goes the same way: OK setVolume followed by simple volume changed: 0.000000

It's as if vlc reacted to a setVolume command by resetting the volume to zero again.

Has anybody some clue about this behaviour of vlc?

Thanks in advance.

mfkl
Developer
Developer
Posts: 739
Joined: 13 Jun 2017 10:41

Re: Can't set volume for vlc player

Postby mfkl » 21 Aug 2023 06:04

Please share a minimal reproducible example we can test locally.
https://mfkl.github.io

User avatar
Kenemtef
New Cone
New Cone
Posts: 4
Joined: 16 Aug 2023 13:15

Re: Can't set volume for vlc player

Postby Kenemtef » 13 Sep 2023 14:04

Hi. Sorry about all the time without news, I simply couldn't reply until now.

Due to the eight thousand characters limit I'm replying in several posts instead of just one.

This is a test application we're using to test the functionality. I'm including it in full in this zip: https://drive.google.com/file/d/1PDoiUL ... sp=sharing. It consists of two java classes, a "video" folder with a video an a "vlc" folder with all that's needed to run vlc (including vlc.exe).

As mentioned before, this is the structure of the "vlc" folder:
Image

The first of the two java classes is this, and it just runs vlc.exe on a process and a thread. While that thread is running, it reads vlc's standard output and prints every one of its lines to the standard options:

Code: Select all

import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.IOException; public class ProcessAndThread implements Runnable{ final String vlcCmd = "vlc//vlc.exe"; private Process process = null; private PrintStream in = null; private BufferedReader out = null; private String processName = ""; public ProcessAndThread() { } public Process createProcess() throws Exception { ProcessBuilder builder; try { builder = new ProcessBuilder(vlcCmd); process = builder.start(); System.out.println("Process " + process + " created"); return process; } catch (Exception e) { throw new Exception (new StringBuilder("Error creating process: ").append(e.getMessage()).toString(), e); } } public PrintStream processInput() throws Exception { try { in=new PrintStream(process.getOutputStream()); return in; } catch (Exception e) { throw new Exception (new StringBuilder("Error gettin process' input: ").append(e.getMessage()).toString(), e); } } public BufferedReader processOutput() throws Exception { try { out=new BufferedReader(new InputStreamReader(process.getInputStream())); return out; } catch (Exception e) { throw new Exception (new StringBuilder("Error gettin process' output: ").append(e.getMessage()).toString(), e); } } public String createThread() throws Exception { try { Thread thread=new Thread(this); thread.setName("VlcManager"); processName=thread.getName(); thread.start(); System.out.println("Now we have created a thread for the process " + process); return processName; } catch (Exception e) { throw new Exception (new StringBuilder("Error building VlcManager: ").append(e.getMessage()).toString(), e); } } public void run() { // The run method of the ProcessAndThread class just reads the output of the process and prints it on the standard output String line = ""; while (true) { try { line = out.readLine(); if (line != null) { System.out.println("["+ processName + "]: read " + line); } else { try { process.exitValue(); } catch (IllegalThreadStateException e){ continue; //El proceso aún está en ejecución } } } catch (IOException e) { System.out.println("["+processName+"]: Error while reading process' output: " + e.getMessage()); break; } } } }
On the next post, I'm sharing the other java class as well as explaining our tests.

Best regards.

User avatar
Kenemtef
New Cone
New Cone
Posts: 4
Joined: 16 Aug 2023 13:15

Re: Can't set volume for vlc player

Postby Kenemtef » 13 Sep 2023 14:15

Hello again. And now, this is the class that uses the one shared in the previous post and does the following:
  • Load the video on video\video.mov
  • Does a setVolume
  • Starts (plays) the video
  • Does another setVolume
  • Pauses the video
  • Does yet another setVolume
  • Stops the video
  • Does the final setVolume. This one must fail, as the video has been unloaded.
  • Ends
Here is the code:

Code: Select all

import java.io.File; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.lang.reflect.Field; public class VlcManager { final static String video = ".\\video\\video.mov"; static final int RETRIES =300; private static boolean error=false; private static boolean fileReady=false; private static Process process = null; private static PrintStream in = null; private static BufferedReader out = null; private static String processName = ""; private VlcManager() { } private static void createProcessAndThread() throws Exception { try { ProcessAndThread processAndThread = new ProcessAndThread(); process = processAndThread.createProcess(); in = processAndThread.processInput(); out = processAndThread.processOutput(); processName = processAndThread.createThread(); } catch (Exception e) { throw new Exception (new StringBuilder("Exception on createProcessAndThread: ").append(e.getMessage()).toString(), e); } } private static void waitBetweenSteps() { try { Thread.sleep(5000); } catch (InterruptedException ie) { System.out.println("Error on thread sleep"); error = true; } } private static void writeSeparator() { System.out.println(); System.out.println("======================================================================================================"); System.out.println(); } private static void sendCommand(String command){ System.out.println("Sending command " + command); in.print(command+"\n"); in.flush(); } public static void main(String[] args) { try { createProcessAndThread(); } catch (Exception e) { System.out.println(e.getMessage()); error = true; } // Step 1: File load if (!error) { writeSeparator(); System.out.println("We are about to send the load command with file = " + video); sendCommand("load "+video); writeSeparator(); // Still in step 1, we allow for a number of retries. // We wait for a message of "OK load" on the process int i = 0; while ((!fileReady) && (!error) && (i < RETRIES)) { try { String line = out.readLine(); if (line.startsWith("OK load")) { fileReady = true; System.out.println("Vídeo load OK"); continue; } if (line.startsWith("KO load")) { error = true; System.out.println("Error loading video"); break; } i++; } catch (IOException e) { System.out.println("Error reading process output: " + e.getMessage()); error = true; break; } } if (i >= RETRIES) { error= true; System.out.println("Maximum allowed number of video load retries reached. Ending on error"); } } waitBetweenSteps(); // Step 2: We send a setVolume on video loaded but stopped if (!error) { writeSeparator(); System.out.println("SetVolume 40 after load, before play"); float volume = 40; sendCommand(new StringBuilder("setVolume ").append(volume).toString()); writeSeparator(); } waitBetweenSteps(); // Step 3: We start the video. if (!error) { writeSeparator(); System.out.println("Start playing vídeo"); sendCommand("play"); writeSeparator(); } waitBetweenSteps(); // Start 4: We send a setVolume on video playing if (!error) { writeSeparator(); System.out.println("SetVolume 75 after play"); float volume = 75; sendCommand(new StringBuilder("setVolume ").append(volume).toString()); writeSeparator(); } waitBetweenSteps(); // Step 5: We pause the video if (!error) { writeSeparator(); System.out.println("We pause the vídeo"); sendCommand("pause"); writeSeparator(); } waitBetweenSteps(); // Step 6: We do a setVolume on paused video if (!error) { writeSeparator(); System.out.println("SetVolume 60 after pause"); float volume = 60; sendCommand(new StringBuilder("setVolume ").append(volume).toString()); writeSeparator(); } waitBetweenSteps(); // Step 7: We stop the video if (!error) { writeSeparator(); System.out.println("We stop the vídeo"); sendCommand("stop"); writeSeparator(); } waitBetweenSteps(); // Step 8: We do a setVolume on stopped video. This returns a KO changeVolume, it's expected and it should be the // one time the "simple volume changed: 0.000000" messages don't appear, as volume WASN'T succesfully changed. if (!error) { writeSeparator(); System.out.println("SetVolume 30 after stop"); float volume = 30; sendCommand(new StringBuilder("setVolume ").append(volume).toString()); writeSeparator(); } waitBetweenSteps(); // Step 9: We try to end the process if (!error) { writeSeparator(); System.out.println("Ending program"); sendCommand("quit"); writeSeparator(); } System.exit(0); } }

On running this one, you should see a window with a 46 seconds video, but no audio. The video does have audio, and it's loud. But I've explained before, on the standard output you'll see these messages:
Image

Which shows that after every succesful setVolume, volume gets reseted to 0.

You'll also see that on failing the last setVolume, these messages doesn't appear. As I said, it's only on a successful setVolume.

Finally, you can run the vlc.exe by itself on the vlc folder on a system command window, and try the following commands:
  • load <file>
  • play
  • pause
  • stop
  • setVolume <volume>
It might give you a better idea of the problem.

Thanks in advance.

mfkl
Developer
Developer
Posts: 739
Joined: 13 Jun 2017 10:41

Re: Can't set volume for vlc player

Postby mfkl » 18 Sep 2023 06:28

vlc.exe load video.mp4 can't be right, so I don't know what command you're using there. The rest looks similar to the RC commands.

Try 'volume <volume>' instead of 'setVolume <volume>', maybe that works. Otherwise not sure, you should probably be using the remote control interface.
https://mfkl.github.io

User avatar
Kenemtef
New Cone
New Cone
Posts: 4
Joined: 16 Aug 2023 13:15

Re: Can't set volume for vlc player

Postby Kenemtef » 18 Sep 2023 08:05

+Hello. Thanks for your answer.

As you suggested, I changed all occurrences of 'setVolume <volume>' for 'volume <volume>'. This returns a message of KO volume:

Image

While 'setVolume <volume>' returns OK volume but then inmediately changes it back to 0.

Image

I'm thinking this is a customized program made to accept just a few commands (load, play, pause, stop) and it was made to accept setVolume instead of volume. But as it's an .exe instead of a .jar, it may have been made in C++.

I may have to build a new .exe in C++ from scratch. libvlc_audio_set_volume accepts two parameters, being the second one the volume, which must be an integer, not a float, is that right?

Thanks in advance.


Return to “Development around libVLC”

Who is online

Users browsing this forum: No registered users and 7 guests