devopvoid / webrtc-java

WebRTC for desktop platforms running Java
Apache License 2.0
248 stars 60 forks source link

Can't specify audio device (recording and playout) #33

Closed javmarina closed 2 years ago

javmarina commented 2 years ago

Describe the bug When using AudioDeviceModule.setRecordingDevice() or AudioDeviceModule.setPlayoutDevice(), the passed device is not used sometimes. Instead, the first device returned by MediaDevices.getAudioCaptureDevices() or MediaDevices.getAudioRenderDevices() is used (respectively).

To Reproduce

final List list = MediaDevices.getAudioCaptureDevices(); final AudioDevice audioDevice = list.get(1); // As an example

final AudioDeviceModule audioDeviceModule = new AudioDeviceModule(); audioDeviceModule.setRecordingDevice(audioDevice);

final PeerConnectionFactory factory = new PeerConnectionFactory(audioDeviceModule); peerConnection = factory.createPeerConnection(defaultConfiguration, ...);

final AudioOptions audioOptions = new AudioOptions(); audioOptions.echoCancellation = false; audioOptions.autoGainControl = false; audioOptions.noiseSuppression = false; final AudioSource audioSource = factory.createAudioSource(audioOptions); final AudioTrack audioTrack = factory.createAudioTrack("audioTrack", audioSource); final RTCRtpSender audioSender = peerConnection.addTrack(audioTrack, List.of("stream"));

// ... Establish connection with signaling server, etc

// Connection is established correctly (that is not the issue). But the selected device is not used. For example, if the list returns "Headphone microphone" (index 0) and "PC microphone" (index 1), the headphone is always used (you can test by blowing on it). The same happens with playout devices: the list is "Speaker" (0) and "Headphone" (1). The sound is always played through the speakers.

Expected behavior The device passed to the method is used for playout/recording.

Desktop (please complete the following information):

Additional context The native implementation of setPlayoutDevice() iterates over the available devices and checks whether each of them corresponds to the function argument. However, if not match is found, the index variable will have a value of 0, and thus the fist device will be selected for playout, regardless of the function argument. This means that the issue likely lies in this line (the if condition). It could be that the GUID is not handled consistently, or PlayoutDeviceName() returns -1.

This is also applicable to setRecordingDevice(), which has an identical structure.

devopvoid commented 2 years ago

Hi @javmarina, thanks for the report. Sorry for the late response. I think you forgot to call audioDeviceModule.initRecording();, same for initPlayout(). You can do that prior creating the PeerConnectionFactory.

javmarina commented 2 years ago

It worked! Thanks 😁

devopvoid commented 2 years ago

This may be relevant here as well: https://github.com/devopvoid/webrtc-java/issues/29#issuecomment-979926225