有可能在Twilio群组视频中进行音高转换吗?

有可能在Twilio群组视频中进行音高转换吗?,twilio,twilio-video,Twilio,Twilio Video,我们已经构建了一个web应用程序。该应用程序的核心是在web上安排会议。因此,用户A(会议协调员)将安排一次会议/会话,所有其他参与者B、C、D等将加入会议/会话。所以我使用了Twilio群组视频通话来实现它 我有下面的用例。 我们想对用户A(会议协调员)的声音进行音调转换。因此,所有其他参与者都将在群组视频中接收音调变化的声音。我们在Twilio中分析了AWS Polly,但它与我们的用例不匹配 因此,请告知Twilio中是否有任何服务可以实现此场景。 (或) 是否可以中断Twilio通话并将

我们已经构建了一个web应用程序。该应用程序的核心是在web上安排会议。因此,用户A(会议协调员)将安排一次会议/会话,所有其他参与者B、C、D等将加入会议/会话。所以我使用了Twilio群组视频通话来实现它

我有下面的用例。 我们想对用户A(会议协调员)的声音进行音调转换。因此,所有其他参与者都将在群组视频中接收音调变化的声音。我们在Twilio中分析了AWS Polly,但它与我们的用例不匹配

因此,请告知Twilio中是否有任何服务可以实现此场景。
(或) 是否可以中断Twilio通话并将音调变化的声音传递给其他参与者

使用的示例代码

initAudio();

function initAudio() {

analyser1 = audioContext.createAnalyser();
analyser1.fftSize = 1024;
analyser2 = audioContext.createAnalyser();
analyser2.fftSize = 1024;

if (!navigator.getUserMedia)
    navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

if (!navigator.getUserMedia)
    return(alert("Error: getUserMedia not supported!"));

navigator.getUserMedia({ audio: true }, function(stream){
    gotStream(stream);
}, function(){ console.log('Error getting Microphone stream'); });

if ((typeof MediaStreamTrack === 'undefined')||(!MediaStreamTrack.getSources)){
    console.log("This browser does not support MediaStreamTrack, so doesn't support selecting sources.\n\nTry Chrome Canary.");
} else {
    MediaStreamTrack.getSources(gotSources);
}
}
function gotStream (stream) {
audioInput = audioContext.createMediaStreamSource(stream);
outputMix = audioContext.createGain();
dryGain = audioContext.createGain();
wetGain = audioContext.createGain();
effectInput = audioContext.createGain();
audioInput.connect(dryGain);
audioInput.connect(effectInput);
dryGain.connect(outputMix);
wetGain.connect(outputMix);
audioOutput = audioContext.createMediaStreamDestination();
outputMix.connect(audioOutput);
outputMix.connect(analyser2);
crossfade(1.0);
changeEffect();
}
    function crossfade (value) {
        var gain1 = Math.cos(value * 0.5 * Math.PI);
        var gain2 = Math.cos((1.0 - value) * 0.5 * Math.PI);

    dryGain.gain.value = gain1;
    wetGain.gain.value = gain2;
}

function createPitchShifter () {
    effect = new Jungle( audioContext );
    effect.output.connect( wetGain );
    effect.setPitchOffset(1);
    return effect.input;
}

function changeEffect () {
    if (currentEffectNode)
        currentEffectNode.disconnect();
if (effectInput)
    effectInput.disconnect();

var effect = 'pitch';

switch (effect) {
    case 'pitch':
        currentEffectNode = createPitchShifter();
        break;
}

audioInput.connect(currentEffectNode);
}
将Localaudiotrack添加到房间时遇到错误

var mediaStream = new Twilio.Video.LocalAudioTrack(audioOutput.stream);

room.localParticipant.publishTrack(mediaStream, {
    name: 'adminaudio'
});
错误:
未捕获(承诺中)TypeError:未能在“MediaStream”上执行“addTrack”:参数1不是“MediaStreamTrack”类型。

Twilio developer evangelist here

在Twilio本身中,音高不会改变声音


如果您是在浏览器中构建的,那么您可以使用Web Audio API从用户的麦克风获取输入,并对其进行音调变换,然后将合成的音频流提供给视频API,而不是原始的麦克风流。

以上答案中的注释非常有用!我已经对此进行了几周的研究,在Twilio-video.js上发布了一篇文章,但没有任何效果,最后用了正确的措辞在S.O上发布了这篇文章

但要总结并补充我发现的有用之处,因为很难理解所有27个问题/评论/代码摘录:

连接到Twilio时:

const room = await Video.connect(twilioToken, {
          name: roomName,
          tracks: localTracks,
          audio: false, // if you don't want to hear the normal voice at all, you can hide this and add the shifted track upon participant connections 
          video: true,
          logLevel: "debug",
        }).then((room) => {
          
          return room;
        });

在新的(远程)参与者连接时:

        const stream = new MediaStream([audioTrack.mediaStreamTrack]);
        const audioContext = new AudioContext(); 
        const audioInput = audioContext.createMediaStreamSource(stream);

source.disconnect(audioOutput);
          console.log("using PitchShift.js");
          var pitchShift = PitchShift(audioContext);

          if (isFinite(pitchVal)) {
            pitchShift.transpose = pitchVal;
            console.log("gain is " + pitchVal);
          }
          pitchShift.wet.value = 1;
          pitchShift.dry.value = 0.5;

          try {
            audioOutput.stream.getAudioTracks()[0]?.applyConstraints({
              echoCancellation: true,
              noiseSuppression: true,
            });
          } catch (e) {
            console.log("tried to constrain audio track " + e);
          }

          var biquadFilter = audioContext.createBiquadFilter();
          // Create a compressor node
          var compressor = audioContext.createDynamicsCompressor();
          compressor.threshold.setValueAtTime(-50, audioContext.currentTime);
          compressor.knee.setValueAtTime(40, audioContext.currentTime);
          compressor.ratio.setValueAtTime(12, audioContext.currentTime);
          compressor.attack.setValueAtTime(0, audioContext.currentTime);
          compressor.release.setValueAtTime(0.25, audioContext.currentTime);
          //biquadFilter.type = "lowpass";
          if (isFinite(freqVal)) {
            biquadFilter.frequency.value = freqVal;
            console.log("gain is " + freqVal);
          }
          if (isFinite(gainVal)) {
            biquadFilter.gain.value = gainVal;
            console.log("gain is " + gainVal);
          }
          source.connect(compressor);
          compressor.connect(biquadFilter);
          biquadFilter.connect(pitchShift);
          pitchShift.connect(audioOutput);
   
        const localAudioWarpedTracks = new Video.LocalAudioTrack(audioOutput.stream.getAudioTracks()[0]);

        const audioElement2 = document.createElement("audio");
        document.getElementById("audio_div").appendChild(audioElement2);

        localAudioWarpedTracks.attach();


你好,欢迎来到Stackoverflow!你能说明一下你为什么要做声调吗?这一切的最终目标是什么?包含这些信息(通过编辑您的问题)非常有用,因为这可能会导致回答者建议另一种方法来达到相同的目标。如何将生成的音频流提供给视频API,而不是原始的麦克风流?我们已经搜索了很多来提供它,但无法找到解决方案尝试在初始化
LocalAudioTrack
时使用
destination.stream
而不仅仅是
destination
。是的,请在下面查找音调转换
var audioContext=new audioContext()的代码;audioInput=audioContext.createMediaStreamSource(流);outputMix=audioContext.createGain();dryGain=audioContext.createGain();wetGain=audioContext.createGain();音频输入。连接(干增益);干增益连接(输出混合);湿增益连接(输出混合);outputMix.connect(audioContext.destination);outputMix.connect(分析仪2);交叉衰减(1.0);changeffect()酷,因此代码显示您正在将混音连接到默认的audioContext目标,通常是扬声器。您应该创建mediaStream目标,并将outputMix连接到该目标,然后在
LocalAudioTrack
中使用它。目标是您将音频发送到的地方。默认的
audioContext.destination
是扬声器。您希望将音频发送到媒体流,然后将其转换为
LocalAudioTrack
。因此,您可以使用
MSdestination=audioContext.createMediaStreamDestination()
创建媒体流目标。将上一个音频节点
outputMix
连接到新的目标:
outputMix.connect(MSdestination)
。最后,您可以使用目的地创建如下
LocalAudioTrack
lat=newlocalaudiotrack(MSdestination.stream)
。这有意义吗?