I have a Java program which record audio using mixer on a Raspberry Pi. I am using ProcessBuilder to achieve this and was working fine last year. Now it doesn't however, and I get the following error when running the application as root:
Starting Starting recording /tmp/test.wav - 19:14:36.64 /usr/bin/arecord -f dat /tmp/test.wav Exception: Command exited with code: 1 with output: arecord: main:830: audio open error: No such file or directory
java.lang.Exception: Command exited with code: 1 with output: arecord: main:830: audio open error: No such file or directory
at Main.record(Main.java:38) at Main.main(Main.java:11)
When I run as the default 'pi' user (java -jar audioTest.jar) it runs fine.
The only difference between last year is that I am now compiling to Java 11 instead of 8 and possibly running on a newer version of Raspbian OS (11 bullseye).
I have it running with nohup through an init.d script so it is running as the root user. This is also required to access the GPIO of the Raspberry as far as I know.
This is my test code:
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) {
System.out.println("Starting");
record(new File("/tmp/test.mp3"));
}
public static void record(File file) {
try {
String wavFile = file.getAbsolutePath().substring(0, file.getAbsolutePath().lastIndexOf(".")) + ".wav";
try {
String player = "/usr/bin/arecord";
ProcessBuilder pb = new ProcessBuilder(player, "-f", "dat", wavFile);
pb.redirectErrorStream(true);
System.out.println("Starting recording " + wavFile + " - " + new SimpleDateFormat("HH:mm:ss.S").format(new Date()));
System.out.println(String.join(" ",pb.command().toArray(new String[0])));
//Process pr = pb.start();
Process recorderProcess = pb.start();
BufferedReader error = new BufferedReader(new InputStreamReader(recorderProcess.getInputStream()));
String errorLine;
StringBuilder accErrorString = new StringBuilder();
while ((errorLine = error.readLine()) != null) {
accErrorString.append(errorLine).append("\n");
}
int exitVal = recorderProcess.waitFor();
if (exitVal != 0) {
throw new Exception("Command exited with code: " + exitVal + " with output: " + accErrorString);
}
} catch (java.io.IOException ioex) {
// This would be the normal exit it seems.
}
} catch (Exception ex){
System.out.println("Exception: " + ex.getMessage());
ex.printStackTrace(System.out);
}
}
}
Any idea why this is happening would be greatly appreciated.
[Edit] The output of record -l:
**** List of CAPTURE Hardware Devices ****
card 3: Device [USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
But adding -D hw:0,0 now gives the error on both. So for th e'pi' user it might select it correctly and not for the root. With hw:3,0 it works, and then add the -c 1 flag to select the channel.