提问人:Paramesh 提问时间:3/26/2014 更新时间:7/27/2015 访问量:1398
Jitsi - 在通话期间播放 WAV 文件 - 如果可能,请与音频混合
Jitsi - Playing a WAV file during call - If possible, mix with audio
问:
我正在自定义 Jitsi 以在通话进行时播放 Wav 文件。
我遇到了麻烦,如果您能帮助我,我将不胜感激。
我可以在调用开始之前切换数据源,方法是使用自定义 AudioFileMediaDevice 并在 CallPeerMediaHandler 中将其打开。
但是在调用过程中,我在替换数据源时遇到了问题。
=============================================================
我尝试了以下方法,但无法使其工作。
1)我尝试获取设备的输出数据源,并使用addInDataSource方法添加了wav文件的URLDatasource。没用。
DataSource dataSource = device.createOutputDataSource();
DataSource fileDataSource = Manager.createDataSource(new URL("file://resources/sounds/Sample.wav"));
((AudioMixingPushBufferDataSource)dataSource).addInDataSource(fileDataSource);
2)我尝试添加自定义捕获设备并切换它,但它也不起作用:
CaptureDeviceInfo2 fileDevice =
new CaptureDeviceInfo2("Recorded Audio 1",
fileDataSource.getLocator(), null, null, null, null);
((MediaServiceImpl) LibJitsi.getMediaService())
.getDeviceConfiguration().getAudioSystem().setDevice(AudioSystem.DataFlow.CAPTURE, fileDevice, false);
不过,这适用于播放,而不是作为捕获设备。
3)我什至尝试添加一个新的音频系统,将播放设备作为文件数据源,但这也不起作用。
=============================================================
我是libjitsi的新手,所以我很难尝试解码正在发生的事情。 关于如何解决这个问题的任何指示都很棒。
答:
我用这段代码在通话中发出了播放声音:
public void startPlaying(CallPeer callPeer, DataSource soundDataSource) throws OperationFailedException {
assert callPeer instanceof CallPeerSipImpl;
CallPeerSipImpl cp = (CallPeerSipImpl) callPeer;
AudioMediaStreamImpl audioMediaStream = (AudioMediaStreamImpl) cp.getMediaHandler().getStream(MediaType.AUDIO);
AudioMediaDeviceSession deviceSession = audioMediaStream.getDeviceSession();
assert deviceSession != null;
assert deviceSession.getDevice() instanceof AudioMixerMediaDevice;
AudioMixerMediaDevice dev = (AudioMixerMediaDevice) deviceSession.getDevice();
dev.getAudioMixer().addInDataSource(soundDataSource);
}
请注意,AudioMixerMediaDevice.getAudioMixer() 在 libjitsi 中具有私有访问权限,因此我将其公开并重新编译。
我需要在通话期间播放音频文件,但只能在通话的远程端播放。因此,我稍微玩了一下stokitos示例,并根据需要对其进行了修改。如果有人需要它,这是我所做的:
private void playAudioFromDataSource(final CallPeerSipImpl callPeer, final DataSource audioDataSource, final MediaDirection direction) {
final CallPeerMediaHandlerSipImpl mediaHandler = callPeer.getMediaHandler();
final AudioMediaStreamImpl audioMediaStream = (AudioMediaStreamImpl) mediaHandler.getStream(AUDIO);
final AudioMediaDeviceSession deviceSession = audioMediaStream.getDeviceSession();
if (null != deviceSession) {
if (RECVONLY == direction) {
// plays audio local only:
deviceSession.addPlaybackDataSource(audioDataSource);
} else {
final AudioMixerMediaDevice mediaDevice = (AudioMixerMediaDevice) deviceSession.getDevice();
final AudioMixer audioMixer = getAudioMixer(mediaDevice);
if (null != audioMixer) {
if (SENDONLY == direction) {
// plays audio remote only:
audioMixer.getLocalOutDataSource().addInDataSource(audioDataSource);
} else if (SENDRECV == direction) {
// plays audio on both sides of call (local and remote):
audioMixer.addInDataSource(audioDataSource);
}
}
}
}
}
private AudioMixer getAudioMixer(final AudioMixerMediaDevice device) {
try {
final Method privateGetAudioMixerMethod = device.getClass().getDeclaredMethod("getAudioMixer");
privateGetAudioMixerMethod.setAccessible(true);
final Object audioMixerObject = privateGetAudioMixerMethod.invoke(device, (Object[]) null);
return (AudioMixer) audioMixerObject;
} catch (final Exception e) {
log.error("Could not get AudioMixer", e);
}
return null;
}
注意:我起诉了反射以获取私有 AudioMixer 对象。我承认这不是最干净的方法,但它有效。:)
评论