gpt4 book ai didi

html - 奇怪的WebRTC SinkID问题

转载 作者:行者123 更新时间:2023-12-03 01:20:38 25 4
gpt4 key购买 nike

我有8条虚拟音频线。我正在尝试将不同的音频/视频播放器映射到不同的虚拟线路,因为我们将其用于远程解释。我的问题是,当出现新的WebRTC时,所有播放器默认都使用最新的sinkID类型。接收器ID的报告没有改变,但是所有音频开始流经最近设置的接收器ID。有人知道这是浏览器限制还是什么?

仅当我在人们连接时按需创建音频播放器时,才会发生这种情况。如果在每个人都连接好之后设置ID,就没有问题。我什至尝试通过所有新连接将所有接收器ID重置为它们应具有的状态,但是音频仍然全部流过最新音频播放器上的接收器ID。

我已附上所有内容的外观。在附件中,Dave将被附加到第4行的SinkID。这很好。如果另一个解释器加入了他加禄语,也可以在第4行听到他们的声音。问题是,如果有人加入说西类牙语,当我在西类牙语(第3行)中设置播放器的接收器ID时,所有音频都通过SinkID听到即使第4行的人员的SinkID仍设置为第4行,第3行也是如此。我认为这可能是Chrome Bug。我使用的是OpenTok(tokbox),实际上不需要显示一些PHP即可管理显示的语言。我已经附加了管理所有这些的iFrame代码。

View of Interface

<!DOCTYPE html>
<html>
<head>
<title>IRIS Remote Player</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="../vendor/jquery/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<link href="/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<script src="https://static.opentok.com/v2/js/opentok.js"></script>
<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>
<meta name="lastLoaded" content="2020-04-21 11:34:57">
<script> var EnglishOn; </script>
<style>
.slow .toggle-group { transition: left 0.7s; -webkit-transition: left 0.7s; }
.fast .toggle-group { transition: left 0.1s; -webkit-transition: left 0.1s; }
.quick .toggle-group { transition: none; -webkit-transition: none; }
</style>
</head>
<body>
<button type="button" class="btn btn-lg btn-danger form-control" id="connect">Connect Remote Interpreters</button>
<div class="container-fluid">
<div class="row live" style="display:none;background:black;color:white;padding-bottom:5px">
<div class="col-sm-2"><input type="checkbox" checked data-width="100%" id="AllAudio" data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="Live" data-off="Break" data-style="quick"></div>
<div class="col-sm-2"><input type="checkbox" checked data-width="100%" id="Admins" data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="Admins Live" data-off="Admins Off" data-style="quick"></div>
</div>

<div class="row live" style="display:none;background:#fff;color:black">
<div class="col-sm-2" id="PL"><input data-style="quick" type="checkbox" class="Interpretation AudioControl SwitchPL" data-width="100%" id="floorPolish" data-lang="PL" data-toggle="toggle" checked data-offstyle="danger" data-onstyle="success" data-on="Polish" data-off="Floor"><br />Floor<br /><audio autoplay controls muted id="englishPolish" class="englishPL"></audio></div><div class="col-sm-2" id="RU"><input data-style="quick" type="checkbox" class="Interpretation AudioControl SwitchRU" data-width="100%" id="floorRussian" data-lang="RU" data-toggle="toggle" checked data-offstyle="danger" data-onstyle="success" data-on="Russian" data-off="Floor"><br />Floor<br /><audio autoplay controls muted id="englishRussian" class="englishRU"></audio></div><div class="col-sm-2" id="ES"><input data-style="quick" type="checkbox" class="Interpretation AudioControl SwitchES" data-width="100%" id="floorSpanish" data-lang="ES" data-toggle="toggle" checked data-offstyle="danger" data-onstyle="success" data-on="Spanish" data-off="Floor"><br />Floor<br /><audio autoplay controls muted id="englishSpanish" class="englishES"></audio></div><div class="col-sm-2" id="TL"><input data-style="quick" type="checkbox" class="Interpretation AudioControl SwitchTL" data-width="100%" id="floorTagalog" data-lang="TL" data-toggle="toggle" checked data-offstyle="danger" data-onstyle="success" data-on="Tagalog" data-off="Floor"><br />Floor<br /><audio autoplay controls muted id="englishTagalog" class="englishTL"></audio></div><div class="col-sm-2" id="EN"><input type="checkbox" data-style="quick" class="AudioControl" data-width="100%" id="floorEnglish" data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="English" data-off="Floor"><br />Floor<br /><audio autoplay controls muted id="englishEnglish" class="englishEN"></audio></div>
</div>
</div>




<script>
var audioSource;
var vars = {};
var floorSource;

$('#connect').click(function() {

$('input:checkbox#Admins').change(function(){
if ($(this).is(':checked')) {
$('.ADMIN').each(function() {
var adminID = $(this).attr("id");
var thisID = adminID.replace("userID", "");
$("#"+thisID).prop('muted', false);
$('#'+thisID).prop('volume', 1);
});
} else {
$('.ADMIN').each(function() {
var adminID = $(this).attr("id");
var thisID = adminID.replace("userID", "");
$("#"+thisID).prop('muted', true);
$('#'+thisID).prop('volume', 0);
});
}
});
$('input:checkbox.AudioControl').change(function(){
var LanguageCode = $(this).attr("data-lang");
var LanguageName = $(this).attr("data-on");
if ($(this).is(':checked')) {
$("#english"+LanguageName).prop('muted', true);
$('#english'+LanguageName).prop('volume', 0);
$("."+LanguageCode).prop('muted', false);
$('.'+LanguageCode).prop('volume', 1);
setTimeout(function(){
if ($('#Admins').is(':checked')) {} else {
$('.ADMIN').each(function() {
var adminID = $(this).attr("id");
var thisID = adminID.replace("userID", "");
$("#"+thisID).prop('muted', true);
$('#'+thisID).prop('volume', 0);
});
}
}, 200);
} else {
//Activate Floor
$("#english"+LanguageName).prop('muted', false);
$('#english'+LanguageName).prop('volume', 1);
$("."+LanguageCode).prop('muted', true);
$('.'+LanguageCode).prop('volume', 0);
setTimeout(function(){
if ($('#Admins').is(':checked')) {} else {
$('.ADMIN').each(function() {
var adminID = $(this).attr("id");
var thisID = adminID.replace("userID", "");
$("#"+thisID).prop('muted', true);
$('#'+thisID).prop('volume', 0);
});
}
}, 200);
}
});

$('input:checkbox#AllAudio').change(function(){
if ($(this).is(':checked')) {
$('.Interpretation').bootstrapToggle('on')
$('#floorEnglish').bootstrapToggle('off')
} else {
$('.AudioControl').bootstrapToggle('off')
}
});

$("#connect").hide();
$("#subscriber").show();
$(".live").show();
playFloor('Polish','PL');
playFloor('Russian','RU');
playFloor('Spanish','ES');
playFloor('Tagalog','TL');
playFloor('English', 'EN');

function playFloor(language, code) {
const audio = document.getElementById('english'+language);
const constraints = {
audio: {deviceId: floorSource},
video: false
};
function handleSuccess(stream) {
const audioTracks = stream.getAudioTracks();
console.log('Got stream with constraints:', constraints);
console.log('Using audio device: ' + audioTracks[0].label);
stream.oninactive = function() {
console.log('Stream ended');
};
window.stream = stream; // make variable available to browser console
audio.srcObject = stream;
}

function handleError(error) {
alert('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}

newSinkID = vars[code];

navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);


//const MyEnglishAudio = document.getElementById("englishPlayer");
audio.setSinkId(newSinkID);
console.log("Setting Audio to: "+newSinkID);

if(code == "EN") {
$("#englishEnglish").prop('muted', false);
$('#englishEnglish').prop('volume', 1);
console.log("Setting English Volume on "+floorSource);
}
}
function handleRemoteError(error) {
if (error) {
alert(error);
}
}




var apiKey = 'HIDEEN';
var sessionId = 'HIDDEN';
var token = 'HIDDEN';

socket = io.connect('/', {
secure: true,
'reconnection': true,
'reconnectionDelay': 1000,
'reconnectionAttempts': Infinity
});


socket.on('disconnect', function () {
console.log("Disconnected from the server");
//location.reload(true);
});

socket.on('send', function (msg) {
fromSocket = msg.split(" ");
to_meeting_id = fromSocket[0];
to_lang = fromSocket[1];
action = fromSocket[2];
who = fromSocket[3];

if(to_meeting_id == '17') {
console.log("Action by "+who+": "+action+" for "+to_lang);
var info = msg.split(" ");
console.log("0: "+info[0]+" 1: "+info[1]+" 2: "+info[2]+" 3: "+info[3]+" 4:"+info[4]+" 5: "+info[5]+" 6: "+info[6]+" 7: "+info[7]);

if(action == "english") {
$('#floorEnglish').bootstrapToggle('on');
$('.Switch'+info[7]).bootstrapToggle('off');
useraudio = document.getElementById(who);
MynewSinkID = vars['EN'];
//useraudio.setSinkId(MynewSinkID);
useraudio.setSinkId(MynewSinkID)
.then(() => {
console.log('successfully set the audio output device - Note Unmuting '+who);
$("#"+who).prop('muted', false);
$('#'+who).prop('volume', 1);
$('#'+who).css("background-color", "green");
})
.catch((err) => {
console.error('Failed to set the audio output device ', err);
});
}
if(action == "englishOff") {
$('#floorEnglish').bootstrapToggle('off');
$('.Switch'+info[6]).bootstrapToggle('on');
// Set Sink Audio Back
useraudio = document.getElementById(who);
MynewSinkID = vars[info[6]];
//useraudio.setSinkId(MynewSinkID);
useraudio.setSinkId(MynewSinkID)
.then(() => {
console.log('successfully set the audio output device');
$('#'+who).css("background-color", "white");
})
.catch((err) => {
console.error('Failed to set the audio output device ', err);
});
}
if(action == "privacyOn") {
$('#floor'+info[4]).bootstrapToggle('off');
}
if(action == "privacyOff") {
$('#floor'+info[4]).bootstrapToggle('on');
}
}

});

console.log("Starting Session");
var session = OT.initSession(apiKey, sessionId);
var AllUsers = [];
i = 0;
// Subscribe to a newly created stream
session.on('streamCreated', function streamCreated(event) {
console.log("New stream in the session: " + event.stream.streamId);
var subscriberOptions = {
insertMode: 'append',
insertDefaultUI: false,
subscribeToAudio: true,
showControls: true,
width: 400,
height: 100,
subscribeToVideo: false
};

console.log("STARTING LOG OF EVENT");
console.log(event);
console.log("END LOG OF EVENT");
parms = event.stream.connection.data;
//alert(parms)
newparms = parms.split(",");
ConnectingID = newparms[0];
Channel = newparms[1];
subscriber = session.subscribe(event.stream, subscriberOptions, handleRemoteError);
console.log("Connecting to event stream: "+event.stream);
//console.log("My Lang: "+MyLang+" VS "+Channel);
item = {}
item ["Channel"] = Channel;
item ["RemoteUserID"] = ConnectingID;
item ["RemoteStream"] = event.stream;
// See if we have seen this user before. If so, remove them from the array so we can readd them after with new stream info
jQuery.each(AllUsers, function(i, val) {
if(val.RemoteUserID == ConnectingID) // delete index
{
//AllUsers.splice(i, 1); // Remove previous streams by this user
}
});
AllUsers.push(item);
console.log(AllUsers);

subscriber.on('videoElementCreated', (event) => {
//console.log("Info "+event.target.stream.connection.data);
var connectionData = event.target.stream.connection.data;
var info = connectionData.split(",")
console.log("User ID: "+info[0]);
console.log("Lang: "+info[1]);
$('#userID'+info[0]).remove();
$.ajax({
type: 'POST',
timeout: 10000,
url: '/ajax/who.php',
dataType: 'html',
data: { "user_id": info[0] },
cache: false,
error: function (jqXHR, exception) {
var msg = '';
if (jqXHR.status === 0) {
msg = 'Can not reach network.\n Verify you have internet.';
} else if (jqXHR.status == 403) {
msg = 'Your five digit code did not match. ';
} else if (jqXHR.status == 404) {
msg = 'Requested page not found. [404]';
} else if (jqXHR.status == 500) {
msg = 'Internal Server Error [500].';
} else if (exception === 'parsererror') {
msg = 'Requested JSON parse failed.';
} else if (exception === 'timeout') {
msg = 'Time out error.';
} else if (exception === 'abort') {
msg = 'Ajax request aborted.';
} else {
msg = 'Uncaught Error.\n' + jqXHR.responseText;
}
alert("Local Server Request: "+msg);
},
success: function (data) {
$('#'+info[1]).append(data);
document.getElementById(info[1]).appendChild(event.element);
setTimeout(function(){
if (data.indexOf('ADMIN') > -1) {
if ($('#Admins').is(':checked')) {} else {
$("#"+info[0]).prop('muted', true);
$('#'+info[0]).prop('volume', 0);
}
}
}, 200);
}
});

console.log("Video Element Created");
console.log(event);
dynamicSinkID = vars[info[1]];
//alert(dynamicSinkID);
event.element.setAttribute("class", "InterpreationSource "+info[1]);
event.element.setAttribute("data-lang", info[1]);
event.element.setAttribute("id", info[0]);
event.element.setAttribute("controls", "controls");
event.element.setAttribute("width", "300");
event.element.setAttribute("height", "54");
if (typeof event.element.sinkId !== 'undefined') {
event.element.setSinkId(dynamicSinkID)
.then(() => {
console.log('successfully set the audio output device');
})
.catch((err) => {
console.error('Failed to set the audio output device ', err);
});
} else {
console.warn('device does not support setting the audio output');
}



// FIX FOR CHROME BUG SETTING LAST PLAYER CREATED AS THE SINKID FOR All - FAILED
/*
setTimeout(function(){
$('.InterpreationSource').each(function() {

var playerID = $(this).attr("id");
var lang_code = $(this).attr("data-lang"); // Get language of each player
var FixID = vars[lang_code]; // Get SinkID it's supposed to be
var theFix = document.getElementById(playerID);
console.log("Fixing "+playerID+" with "+FixID);
theFix.setSinkId(FixID)
.then(() => {
console.log('successfully set the audio output device - Note Unmuting '+playerID);
})
.catch((err) => {
console.error('Failed to set the audio output device ', err);
});
});

}, 2000);
*/
// END FIX BUG FOR CHROME

});

});

session.connect(token, function (error) {
if(error) {
alert(error);
}
});



});


if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("enumerateDevices() not supported.");
}

// List cameras and microphones.

navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
//console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
if(device.kind == "audiooutput" && device.label == "Line 5 (Virtual Audio Cable)") {
vars['EN'] = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
if(device.kind == "audiooutput" && device.label == "Line 1 (Virtual Audio Cable)") {
vars['PL'] = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
if(device.kind == "audiooutput" && device.label == "Line 2 (Virtual Audio Cable)") {
vars['RU'] = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
if(device.kind == "audiooutput" && device.label == "Line 3 (Virtual Audio Cable)") {
vars['ES'] = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
if(device.kind == "audiooutput" && device.label == "Line 4 (Virtual Audio Cable)") {
vars['TL'] = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
if(device.kind == "audioinput" && device.label == "Microphone Array (Synaptics Audio)") {
floorSource = device.deviceId;
console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
}
});
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});


</script>
</body>
</html>

*****编辑*****
看到我的问题可能与 https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/discuss-webrtc/vrw44ZGE0gs/2YJ6yUEjBgAJ有关

WebRTC在内部混合音轨,并且所有音轨的音频实际上都作为单个音频流传输到Chrome。诸如音量之类的属性更改将发送到WebRTC以在混合之前应用。因此,不幸的是,这意味着该混音器的输出只能定向到单个音频设备。

以上适用于和媒体元素。

但是,Chrome提供了一种解决方法,其中涉及通过WebAudio进行渲染。为此,即使不一定要将音频发送到特定设备或将其静音,仍需要从混合流中“拉”音频。
然后,您可以按照此示例克隆远程轨道并通过WebAudio渲染它们。

所以现在我只需要弄清楚该怎么做。

最佳答案

因此,我想出了解决此问题的方法。我创建了一个函数,并使用以下代码通过WebAudio循环了WebRTC音频:

    function addNewStream(event, dynamicSinkID, lang) {     
var mediaStream = event.element.srcObject;
var remote_stream1 = mediaStream.clone();
test_audio_context1 = new AudioContext();
webaudio_source1 = test_audio_context1.createMediaStreamSource(remote_stream1);
webaudio_ms1 = test_audio_context1.createMediaStreamDestination();
webaudio_source1.connect(webaudio_ms1);
test_output_audio1 = new Audio();
test_output_audio1.srcObject = webaudio_ms1.stream;
test_output_audio1.play();
test_output_audio1.setSinkId(dynamicSinkID);
test_output_audio1.setAttribute("controls", "controls");
document.getElementById(lang).appendChild(test_output_audio1);
test_output_audio1.setAttribute("controls", "controls");
test_output_audio1.setAttribute("width", "300");
test_output_audio1.setAttribute("height", "54");
}

关于html - 奇怪的WebRTC SinkID问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61273969/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com