我有一个用asp.net编写的视频应用程序和用JS中的webRTC编写的c#。 有些外包不久前给我写了(不能再联系到他了)应用程序工作得非常好,除了一个问题。 这个视频应用程序是为屏幕共享使用而编写的,它使用一些chrome扩展来进行屏幕共享,这也很有效。问题是,只要您从屏幕共享返回到网络摄像头流,您就无法返回到屏幕共享流。它看起来像程序员这样写的。 我尝试再次打开扩展程序,但它发送给我一个错误。我的问题是,有没有办法可以保存屏幕共享流并更改视频源而不用触摸扩展名? 这是webrtc的js代码: 第三个'if'
中getfeed的主要问题 getFeed = function (shareScreen, username, userType, reinit, cb) {
if (shareScreen) {
$("#screen-share").attr("disabled", "disabled");
$("#video-share").removeAttr("disabled");
// getUserMedia(session, onSuccess, onError);
if (webrtcDetectedBrowser == "chrome") {
DetectRTC.screen.isChromeExtensionAvailable(function (isAvaliabe) {
if (isInScreenSharing) {
return;
}
if (isAvaliabe) {
isInScreenSharing = true;
captureUserMedia(onSuccess);
} else {
alertify.confirm("Screen sharing extension is not installed," +
" do you wish to install it now?",
function(e) {
if (e) {
window.open("https://chrome.google.com/webstore/detail/screen-capturing-
for-micr/hmppjaalobpkbpneompfdpfilcmfhfik", "_blank");
alertify.alert("Click Ok to reload page
after installing extension ", function () {
location.href = location.href;
});
}
});
}
});
} else {
isInScreenSharing = false;
getScreenId(function (error, sourceId, screen_constraints) {
screen_constraints.video = _showWebCam;
screen_constraints.audio = _showWebCam;
getUserMedia(screen_constraints, onSuccess, onError);
});
}
} else {
$("#video-share").attr("disabled", "disabled");
$("#screen-share").removeAttr("disabled");
getUserMedia(
{
// Permissions to request
video: _showWebCam,
audio: _showWebCam
}, onSuccess, onError);
}
function onSuccess(stream) { // succcess callback gives us a media stream
$('.instructions').hide();
if (reinit) {
if (screenStream) {
screenStream.getTracks().forEach(function (e) {
e.stop();
});
screenStream = null;
}
// Store off the stream reference so we can share it later
_mediaStream = stream;
if (webrtcDetectedBrowser == "chrome") {
if (shareScreen) {
//get the audio track from video stream and put it in screeen stream
var audioTrack = videoStream.getAudioTracks()[0];
var screenAudio = stream.getAudioTracks()[0];
if (screenAudio) {
_mediaStream.removeTrack(screenAudio)
}
_mediaStream.addTrack(audioTrack)
screenStream = _mediaStream;
} else {
videoStream = stream;
}
}
// Load the stream into a video element so it starts playing in the UI
console.log('playing my local video feed');
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
if (cb) {
cb();
}
} else {
if (webrtcDetectedBrowser == "chrome") {
videoStream = stream;
}
var gameId =viewModel.GameId();
// Now we have everything we need for interaction, so fire up SignalR
_connect(username, userType,gameId, function (hub) {
// tell the viewmodel our conn id, so we can be treated like the special person we are.
viewModel.MyConnectionId(hub.connection.id);
// Initialize our client signal manager, giving it a
signaler (the SignalR hub) and some callbacks
console.log('initializing connection manager');
connectionManager.initialize(hub.server, _callbacks.onReadyForStream, _callbacks.onStreamAdded, _callbacks.onStreamRemoved);
// Store off the stream reference so we can share it later
_mediaStream = stream;
// Load the stream into a video element so it starts playing in the UI
console.log('playing my local video feed');
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
// Hook up the UI
_attachUiHandlers();
viewModel.Loading(false);
if (cb) {
cb();
}
}, function (event) {
alertify.alert('<h4>Failed SignalR Connection</h4> We were not able to connect you to the signaling server.<br/><br/>Error: ' + JSON.stringify(event));
viewModel.Loading(false);
});
}
}
function onError(error) {
if (webrtcDetectedBrowser == "firefox") {
if (window.location.protocol === "https:") {
alertify.confirm("Screen sharing extension is not installed," +
" do you wish to install it now?",
function (e) {
if (e) {
InstallTrigger.install({ "ScreenShare": { URL: "https://addons.mozilla.org/firefox/downloads/file/457292/easy_screen_sharing_for_microgamecoaching_ltd-1.0.000-fx.xpi" } });
}
});
return;
}
}
alertify.alert(JSON.stringify(error));
viewModel.Loading(false);
}
},
_startSession = function (username, userType, gameId) {
// viewModel.Username(username); // Set the selected username in the UI
viewModel.Loading(true); // Turn on the loading indicator
// viewModel.UserType(userType); // Set the selected username in the UI
//viewModel.GameId(gameId);
if (location.hash === "#ss") {
getFeed(true, username, userType);
} else {
getFeed(false, username, userType);
}
$("#screen-share").click(function () {
getFeed(true, username, userType, true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
// _hub.server.callUser(p,true);
});
});
$("#video-share").click(function () {
getFeed(false, username, userType, true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
// _hub.server.callUser(p, true);
});
});
$("#mute").click(function () {
if (_mediaStream) {
_mediaStream.getAudioTracks().forEach(function (t) {
t.enabled = t.muted = false;
});
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
}
});
$("#unmute").click(function () {
if (_mediaStream) {
_mediaStream.getAudioTracks().forEach(function (t) {
t.enabled = t.muted = true;
});
var videoElement = document.querySelector('.video.mine');
attachMediaStream(videoElement, _mediaStream);
}
});
},
_attachUiHandlers = function() {
// Add click handler to users in the "Users" pane
$(document).on("click", ".user", function () {
var userName = viewModel.Username();
if (!userName) {
alertify.alert("Please log in to enter the room", function() {
location.href = viewModel.LoginUrl() + "?returnUrl="+location.href;
});
return;
}
// Find the target user's SignalR client id
var targetConnectionId = $(this).attr('data-cid');
// Make sure we are in a state where we can make a call
if (viewModel.Mode() !== 'idle') {
alertify.error('Sorry, you are already in a call. Conferencing is not yet implemented.');
return;
}
// Then make sure we aren't calling ourselves.
if (targetConnectionId != viewModel.MyConnectionId()) {
// Initiate a call
_hub.server.callUser(targetConnectionId, false);
// UI in calling mode
viewModel.Mode('calling');
} else {
alertify.error("Ah, nope. Can't call yourself.");
}
});
$('#btnMessageSend').click(function() {
sendChatMessage();
});
$('#inpMessageText').keypress(function (e) {
if (e.keyCode === 13) {
sendChatMessage();
}
});
function sendChatMessage() {
var text = $('#inpMessageText').val();
if (text !== '') {
$('#inpMessageText').val('');
_hub.server.sendMessage(text, viewModel.MyConnectionId(), _callPartner.ConnectionId);
if (_lastMessageMine === null || !_lastMessageMine) {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="autor">You</div><div class="message">' + text + '</div></div>');
} else {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="message">' + text + '</div></div>');
}
_lastMessageMine = true;
}
$('#pnlMessagesContainer .message-container').scrollTop($('#pnlMessagesContainer .message-container').prop("scrollHeight"));
}
// Add handler for the hangup button
$('.hangup').click(function () {
// Only allow hangup if we are not idle
if (viewModel.Mode() != 'idle') {
_hub.server.hangUp(false);
connectionManager.closeAllConnections();
viewModel.Mode('idle');
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
}
});
$('input[name="rbtnWebcamToogle"]').change(function () {
_showWebCam = $(this).val() === "1";
if (!_showWebCam) {
//connectionManager.closeConnection(viewModel.MyConnectionId());
var mediaStream = _mediaStream.getVideoTracks()[0];
mediaStream.stop();
} else {
getFeed(false, viewModel.Username(), viewModel.UserType(), true, function () {
var p = connectionManager.currentPartnerId;
connectionManager.closeAllConnections();
_hub.server.hangUp(true);
});
}
});
},
_setupHubCallbacks = function (hub) {
// Hub Callback: Incoming Call
hub.client.incomingCall = function (callingUser, switching) {
console.log('incoming call from: ' + JSON.stringify(callingUser));
if (switching) {
hub.server.answerCall(true, callingUser.ConnectionId);
// So lets go into call mode on the UI
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + callingUser.Usertype + ': ' + callingUser.Username);
return;
}
// Ask if we want to talk
alertify.confirm(callingUser.Username + ' is calling. Do you want to chat?', function (e) {
if (e) {
// I want to chat
hub.server.answerCall(true, callingUser.ConnectionId);
_callPartner = callingUser;
// So lets go into call mode on the UI
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + callingUser.Usertype + ': ' + callingUser.Username);
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').show();
} else {
// Go away, I don't want to chat with you
hub.server.answerCall(false, callingUser.ConnectionId);
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
}
});
};
// Hub Callback: Call Accepted
hub.client.callAccepted = function (acceptingUser) {
console.log('call accepted from: ' + JSON.stringify(acceptingUser) + '. Initiating WebRTC call and offering my stream up...');
// Callee accepted our call, let's send them an offer with our video stream
connectionManager.initiateOffer(acceptingUser.ConnectionId, _mediaStream);
_callPartner = acceptingUser;
// Set UI into call mode
viewModel.Mode('incall');
$('#videoTitle').html('Your Session is LIVE');
$('#videoPartnerName').html('Your ' + acceptingUser.Usertype + ': ' + acceptingUser.Username);
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').show();
};
// Hub Callback: Call Declined
hub.client.callDeclined = function (decliningConnectionId, reason) {
console.log('call declined from: ' + decliningConnectionId);
_callPartner = null;
// Let the user know that the callee declined to talk
alertify.error(reason);
// Back to an idle UI
viewModel.Mode('idle');
};
// Hub Callback: Call Ended
hub.client.callEnded = function (connectionId, reason, switching) {
console.log('call with ' + connectionId + ' has ended: ' + reason);
if (!switching) {
// Let the user know why the server says the call is over
alertify.error(reason);
connectionManager.closeConnection(connectionId);
// Set the UI back into idle mode
viewModel.Mode('idle');
$('#pnlMessagesContainer .message-container').empty();
$('#pnlChatContainer').hide();
_callPartner = null;
$('#videoTitle').html('Coaching Session');
$('#videoPartnerName').html('');
} else {
connectionManager.closeConnection(connectionId);
_hub.server.callUser(connectionId, true);
}
// Close the WebRTC connection
};
hub.client.receiveMessage = function (senderUser, message) {
if (_lastMessageMine == null || _lastMessageMine) {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="autor">' + senderUser.Username + '</div><div class="message">' + message + '</div></div>');
} else {
$('#pnlMessagesContainer .message-container')
.append('<div><div class="message">' + message + '</div></div>');
}
$('#pnlMessagesContainer .message-container').scrollTop($('#pnlMessagesContainer .message-container').prop("scrollHeight"));
_lastMessageMine = false;
}
// Hub Callback: Update User List
hub.client.updateUserList = function (userList) {
viewModel.setUsers(userList);
};
// Hub Callback: WebRTC Signal Received
hub.client.receiveSignal = function (callingUser, data) {
connectionManager.newSignal(callingUser.ConnectionId, data);
};
},
// Connection Manager Callbacks
_callbacks = {
onReadyForStream: function (connection) {
// The connection manager needs our stream
// todo: not sure I like this
connection.addStream(_mediaStream);
},
onStreamAdded: function (connection, event) {
console.log('binding remote stream to the partner window');
// Bind the remote stream to the partner window
var otherVideo = document.querySelector('.video.partner');
attachMediaStream(otherVideo, event.stream); // from adapter.js
},
onStreamRemoved: function (connection, streamId) {
console.log('removing remote stream from partner window');
// Clear out the partner window
var otherVideo = document.querySelector('.video.partner');
otherVideo.src = '';
}
};
return {
start: _start, // Starts the UI process
getStream: function() { // Temp hack for the connection manager to reach back in here for a stream
return _mediaStream;
}
};
})(WebRtcDemo.ViewModel, WebRtcDemo.ConnectionManager);
// Kick off the app
WebRtcDemo.App.start();
var isChrome = !!navigator.webkitGetUserMedia;
var DetectRTC = {};
(function () {
var screenCallback;
DetectRTC.screen = {
chromeMediaSource: 'screen',
getSourceId: function (callback) {
if (!callback) throw '"callback" parameter is mandatory.';
screenCallback = callback;
window.postMessage('get-sourceId', '*');
},
isChromeExtensionAvailable: function (callback) {
if (!callback) return;
if (DetectRTC.screen.chromeMediaSource == 'desktop') callback(true);
// ask extension if it is available
window.postMessage('are-you-there', '*');
setTimeout(function () {
if (DetectRTC.screen.chromeMediaSource == 'screen') {
callback(false);
} else callback(true);
}, 2000);
},
onMessageCallback: function (data) {
console.log('chrome message', data);
// "cancel" button is clicked
if (data == 'PermissionDeniedError') {
DetectRTC.screen.chromeMediaSource = 'PermissionDeniedError';
if (screenCallback) return
screenCallback('PermissionDeniedError');
else throw new Error('PermissionDeniedError');
}
// extension notified his presence
if (data == 'rtcmulticonnection-extension-loaded') {
DetectRTC.screen.chromeMediaSource = 'desktop';
}
// extension shared temp sourceId
if (data.sourceId) {
DetectRTC.screen.sourceId = data.sourceId;
if (screenCallback) screenCallback(DetectRTC.screen.sourceId);
}
}
};
// check if desktop-capture extension installed.
if (window.postMessage && isChrome) {
DetectRTC.screen.isChromeExtensionAvailable();
}
})();
window.addEventListener('message', function (event) {
if (event.origin != window.location.origin) {
return;
}
DetectRTC.screen.onMessageCallback(event.data);
});
function captureUserMedia(onStreamApproved) {
// this statement defines getUserMedia constraints
// that will be used to capture content of screen
var screen_constraints = {
mandatory: {
chromeMediaSource: DetectRTC.screen.chromeMediaSource,
maxWidth: 1920,
maxHeight: 1080,
minAspectRatio: 1.77
},
optional: []
};
// this statement verifies chrome extension availability
// if installed and available then it will invoke extension API
// otherwise it will fallback to command-line based screen capturing API
if (DetectRTC.screen.chromeMediaSource == 'desktop' && !DetectRTC.screen.sourceId) {
DetectRTC.screen.getSourceId(function (error) {
// if exception occurred or access denied
if (error && error == 'PermissionDeniedError') {
alert('PermissionDeniedError: User denied to share content of his screen.');
}
captureUserMedia(onStreamApproved);
});
return;
}
// this statement sets gets 'sourceId" and sets "chromeMediaSourceId"
if (DetectRTC.screen.chromeMediaSource == 'desktop') {
screen_constraints.mandatory.chromeMediaSourceId = DetectRTC.screen.sourceId;
}
// it is the session that we want to be captured
// audio must be false
var session = {
audio: false,
video: screen_constraints
};
// now invoking native getUserMedia API
navigator.webkitGetUserMedia(session, onStreamApproved, function (error){console.error(error)});
};