Closed Stasyanych closed 2 years ago
I never tried that, due to lack of time. As far as I know, the native WebRTC implementation does not catch a device change, even if you enumerate the devices after one is (dis)connected. The implementation with (dis)connected callbacks is my own. Thus its a bit hard to tell device module to switch the device.
The next thing to consider are the media tracks managed by the peer connection, since each track (mic/cam) is bound to a device. You can switch tracks or the sources of tracks, but if the source is not updated it obviously goes wrong.
I would handle this issue with a low priority.
Thank you for your quick response! I want to share the method that I tried. Maybe it will be useful. I found on the Internet that it is possible to replace a track by calling the sender.replaceTrack method and specify AudioTrack as an input parameter. In the browser implementation WebRTC, it looks something like this::
//...
var audioTrack = stream.getAudioTracks()[0];
var sender = pc.getSenders().find(function(s) {
return s.track.kind == audioTrack.kind;
});
sender.replaceTrack(audioTrack);
//...
I tried to do something similar in the DeviceChangeListener.deviceConnected method. I re-created AudioTrack and tried to replace the track. This did not give a positive result. Code on kotlin::
connection.senders.find {
it.track.kind.equals(MediaStreamTrack.AUDIO_TRACK_KIND)
}?.let { rtcSender ->
val audioOptions = AudioOptions().apply {
this.noiseSuppression = true
this.echoCancellation = true
}
val audioSource = peerConnectionFactory?.createAudioSource(audioOptions)
val audioTrack = peerConnectionFactory?.createAudioTrack("audioTrack", audioSource)
rtcSender.replaceTrack(audioTrack)
}
I also made an attempt to replace
rtcSender.replaceTrack(audioTrack)
on
rtcSender.track.dispose() // otherwise, the removeTrack method will hang
connection.removeTrack(rtcSender)
connection.addTrack(audioTrack, listOf("stream"))
also to no avail
Hi @Stasyanych, this should work at runtime when the media is already flowing and you send/receive audio:
AudioDevice captureDevice; // Get desired device.
AudioDevice playbackDevice; // Get desired device.
AudioDeviceModule deviceModule = new AudioDeviceModule();
// For sending audio.
deviceModule.setRecordingDevice(captureDevice);
deviceModule.initRecording();
// For receiving audio.
deviceModule.setPlayoutDevice(playbackDevice);
deviceModule.initPlayout();
PeerConnectionFactory factory = new PeerConnectionFactory(deviceModule);
// Initialize PeerConnection and establish connection.
// Change audio recording and playback device at runtime.
// For sending audio.
deviceModule.stopRecording();
deviceModule.setRecordingDevice(newRecordingDevice);
deviceModule.initRecording();
deviceModule.startRecording();
// For receiving audio.
deviceModule.stopPlayout();
deviceModule.setPlayoutDevice(newPlaybackDevice);
deviceModule.initPlayout();
deviceModule.startPlayout();
Thank you! I will definitely check it out.
How do I change the audio playback or capture device during an established communication session? For example, if a bluetooth headset was connected during a conversation and there is a need to transfer the stream to it. Is it possible to do this in the current implementation of the library?
I did it like this on Kotlin
The code is given as an example, it does not take into account the connection/disconnection of the microphone, only the playback device. The listener perfectly catches device change events , but
deviceModule.setPlayoutDevice(it)
does not lead to any changes. In thedeviceConnected(device: Device?)
method nothing happens, but in thedeviceDisconnected(device: Device?)
method an exception may appear -Set playout device failed
I'm sure I'm doing something wrong. Is there a way to switch devices dynamically? Thank you in advance for the answer!