In this code I am using Signal + WebRTC to live video. Brief description: The host is live streaming his video to all viewers and viewers when they click on the link will see the host's live video. When the host reloads the page the live video will be updated to all viewers. However I am getting Error: Current signalingState (stable) is not valid for receiving response
if (peer.signalingState !== "have-local-offer") {
console.error(`Lỗi: signalingState hiện tại (${peer.signalingState}) không hợp lệ để nhận answer`);
return;
}
It seems that this is preventing viewers from getting the host's live video. Here is my code:
<script>
var userRole = $('#_typeAccount').val(); // Role (owner/user)
var nameJoin = $('#_nameJoin').val();
var avatarJoin = $('#_avatarJoin').val();
var profileJoin = $('#_profileJoin').val();
var roomGet = $('#_roomLocal').val();
var ownerGet = $('#_ownerID').val();
$(function () {
let containerLive = document.getElementById("_pnVideoLive");
if (containerLive) {
// Kết nối tới SignalR Hub
var isCamEnabled = true;
var connection = $.hubConnection();
var hubProxy = connection.createHubProxy('videoHub');
var localStream;
var peerConnections = {};
// Hàm lấy stream cho chủ phòng (owner)
function getStreamForOwner(ownerId) {
return new Promise((resolve, reject) => {
let constraints = userRole === "owner"
? { video: true, audio: true } // Nếu là owner, yêu cầu quyền đầy đủ
: { video: true, audio: false }; // Nếu là user, chỉ nhận video
navigator.mediaDevices.getUserMedia(constraints)
.then(function (stream) {
resolve(stream);
})
.catch(function (err) {
reject(err);
});
});
}
hubProxy.on('updateOwnerList', function (owners) {
let videoContainer = document.getElementById("video-container"); // Giả sử đây là nơi chứa video
// Lấy danh sách tất cả video đang có trên giao diện người xem
let existingVideos = videoContainer.querySelectorAll("video");
//Xóa video cũ nếu không có trong danh sách mới
existingVideos.forEach(video => {
let videoId = video.id;
let ownerExists = owners.some(owner => `owner-${owner.UserId}` === videoId);
if (!ownerExists) {
console.log(`Xóa video cũ: ${videoId}`);
video.remove();
}
});
owners.forEach(function (owner) {
let videoId = `owner-${owner.UserId}`;
let existingVideo = document.getElementById(videoId);
if (!existingVideo) {
if (userRole === "user") {
console.log("Người xem tham gia, nhận stream từ chủ phòng");
let newVideo = document.createElement("video");
newVideo.setAttribute("id", videoId);
newVideo.setAttribute("autoplay", "true");
newVideo.setAttribute("playsinline", "true");
videoContainer.appendChild(newVideo);
// Tạo kết nối WebRTC để nhận stream từ owner
let peer = new RTCPeerConnection();
peerConnections[owner.UserId] = peer;
// Khi nhận Offer từ Owner
hubProxy.on("ReceiveOwnerStream", function (ownerId, offerJson) {
if (ownerId === owner.UserId) {
let offer = new RTCSessionDescription(JSON.parse(offerJson));
peer.setRemoteDescription(offer).then(() => {
return peer.createAnswer();
}).then(answer => {
return peer.setLocalDescription(answer);
}).then(() => {
hubProxy.invoke("SendViewerAnswer", ownerId, JSON.stringify(peer.localDescription));
}).catch(error => {
console.error("Lỗi khi xử lý Offer từ chủ phòng:", error);
});
}
});
peer.onicecandidate = function (event) {
if (event.candidate) {
let candidateData = {
candidate: event.candidate.candidate,
sdpMid: event.candidate.sdpMid,
sdpMLineIndex: event.candidate.sdpMLineIndex
};
hubProxy.invoke("SendCandidate", owner.UserId, JSON.stringify(candidateData));
}
};
peer.ontrack = function (event) {
console.log("Nhận stream từ owner:", owner.UserId);
document.getElementById(videoId).srcObject = event.streams[0];
};
}
else if (userRole === "owner") {
console.log("Chủ phòng đang phát trực tiếp:", owners);
getStreamForOwner(owner.UserId).then(function (stream) {
$('#_nosignal').remove();
let newVideo = document.createElement("video");
newVideo.setAttribute("id", videoId);
newVideo.setAttribute("autoplay", "true");
newVideo.setAttribute("playsinline", "true");
videoContainer.appendChild(newVideo);
newVideo.srcObject = stream;
localStream = stream;
let peer = new RTCPeerConnection();
peerConnections[owner.UserId] = peer;
//Thêm Stream vào kết nối WebRTC
stream.getTracks().forEach(track => peer.addTrack(track, stream));
peer.createOffer().then(offer => {
return peer.setLocalDescription(offer);
}).then(() => {
hubProxy.invoke("SendOwnerStream", owner.UserId, JSON.stringify(peer.localDescription));
}).catch(error => {
console.error("Lỗi khi tạo Offer cho chủ phòng:", error);
});
peer.onicecandidate = function (event) {
if (event.candidate) {
let candidateData = {
candidate: event.candidate.candidate,
sdpMid: event.candidate.sdpMid,
sdpMLineIndex: event.candidate.sdpMLineIndex
};
hubProxy.invoke("SendCandidate", owner.UserId, JSON.stringify(candidateData));
}
};
}).catch(function (error) {
handleCameraError(error);
});
}
}
});
});
hubProxy.on("ReceiveOwnerStream", function (ownerId, offerJson) {
if (userRole === "user") {
console.log("Chủ phòng đã bắt đầu stream: " + ownerId);
alert("Chủ phòng đã bắt đầu phát trực tiếp!");
let offer = new RTCSessionDescription(JSON.parse(offerJson)); // Chuyển từ JSON về Object
// Kiểm tra nếu đã có kết nối trước đó
if (peerConnections[ownerId]) {
console.warn(`PeerConnection với ownerId ${ownerId} đã tồn tại.`);
return;
}
// Tạo kết nối WebRTC mới
let peer = new RTCPeerConnection();
peerConnections[ownerId] = peer;
// Khi nhận stream từ chủ phòng
peer.ontrack = function (event) {
let videoId = `owner-${ownerId}`;
let existingVideo = document.getElementById(videoId);
if (!existingVideo) {
let newVideo = document.createElement("video");
newVideo.setAttribute("id", videoId);
newVideo.setAttribute("autoplay", "true");
newVideo.setAttribute("playsinline", "true");
document.getElementById("videoContainer").appendChild(newVideo);
}
document.getElementById(videoId).srcObject = event.streams[0];
};
// Đặt remote description và tạo answer
peer.setRemoteDescription(offer).then(() => {
return peer.createAnswer();
}).then(answer => {
return peer.setLocalDescription(answer);
}).then(() => {
console.log(peer.signalingState);
hubProxy.invoke("SendViewerAnswer", ownerId, JSON.stringify(peer.localDescription));
}).catch(error => {
console.error("Lỗi xử lý offer từ chủ phòng:", error);
});
}
});
hubProxy.on("ReceiveViewerAnswer", function (ownerId, answerJson) {
let answer = new RTCSessionDescription(JSON.parse(answerJson));
let peer = peerConnections[ownerId];
if (!peer) {
console.error(`Không tìm thấy peerConnection cho ownerId: ${ownerId}`);
return;
}
if (peer.signalingState !== "have-local-offer") {
console.error(`Lỗi: signalingState hiện tại (${peer.signalingState}) không hợp lệ để nhận answer`);
return;
}
peer.setRemoteDescription(answer).catch(error => {
console.error("Lỗi khi setRemoteDescription cho owner:", error);
});
});
// Nhận tín hiệu từ server (SignalR)
hubProxy.on('broadcastMessage', function (message) {
console.log("Nhận được tin nhắn:", message);
// Xử lý các tín hiệu WebRTC (mời tham gia, kết nối, v.v.)
if (message.type === 'offer') {
handleOffer(message);
} else if (message.type === 'answer') {
handleAnswer(message);
} else if (message.type === 'candidate') {
handleCandidate(message);
}
});
// Mở kết nối SignalR
connection.start().then(function () {
console.log("Kết nối thành công tới SignalR Hubs");
console.log("Connection ID:", connection.id);
// Gửi tin nhắn đến server khi kết nối thành công
hubProxy.invoke('SetUserRole', userRole, nameJoin, avatarJoin, profileJoin).catch(function (err) {
console.error(err.toString());
});
}).fail(function (err) {
console.error("Không thể kết nối tới SignalR Hub: " + err);
});
// Gửi tin nhắn đến server
function sendMessage(message) {
hubProxy.invoke('SendMessage', message).catch(function (err) {
console.error(err.toString());
});
}
// Xử lý offer từ owner
function handleOffer(offer) {
var peerConnection = new RTCPeerConnection();
peerConnections[offer.senderId] = peerConnection;
peerConnection.setRemoteDescription(new RTCSessionDescription(offer.sdp))
.then(function () {
// Thêm track vào peer connection
if (localStream) {
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});
}
// Tạo answer và gửi lại
return peerConnection.createAnswer();
})
.then(function (answer) {
return peerConnection.setLocalDescription(answer);
})
.then(function () {
sendMessage({ type: 'answer', receiverId: offer.senderId, sdp: peerConnection.localDescription });
})
.catch(function (error) {
console.error("Lỗi xử lý offer: ", error);
});
}
// Xử lý answer từ người xem
function handleAnswer(answer) {
var peerConnection = peerConnections[answer.receiverId];
peerConnection.setRemoteDescription(new RTCSessionDescription(answer.sdp))
.catch(function (error) {
console.error("Lỗi xử lý answer: ", error);
});
}
// Xử lý candidate (ICE candidate) từ peer
function handleCandidate(candidate) {
console.log("Candidate nhận được:", candidate);
if (!candidate || !candidate.candidate) {
console.error("Lỗi: Candidate không hợp lệ!", candidate);
return;
}
var peerConnection = peerConnections[candidate.receiverId];
if (!peerConnection) {
console.error("Không tìm thấy peerConnection cho receiverId:", candidate.receiverId);
return;
}
let iceCandidate = new RTCIceCandidate({
candidate: candidate.candidate,
sdpMid: candidate.sdpMid || null, // Kiểm tra giá trị null
sdpMLineIndex: candidate.sdpMLineIndex || null
});
peerConnection.addIceCandidate(iceCandidate).catch(function (error) {
console.error("Lỗi xử lý ICE Candidate:", error);
});
}
function handleCameraError(error) {
let errorMessage = "Không thể truy cập webcam.";
if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") {
errorMessage = "Quyền truy cập bị từ chối. Vui lòng cấp quyền sử dụng camera và micro.";
} else if (error.name === "NotFoundError" || error.name === "DevicesNotFoundError") {
errorMessage = "Không tìm thấy thiết bị camera hoặc micro.";
} else if (error.name === "NotReadableError" || error.name === "TrackStartError") {
errorMessage = "Thiết bị đang được sử dụng bởi ứng dụng khác.";
}
$('#_cammain span').text(errorMessage);
}
}
});
</script>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744211805a4563369.html
评论列表(0条)