AI: WebRTC: Fix camera/microphone not released after closing publisher. v7.0.106 (#4261)

This commit is contained in:
OSSRS-AI
2025-10-26 08:43:51 -04:00
committed by winlin
parent 9eae868e91
commit 51ab6403a3
5 changed files with 83 additions and 10 deletions

View File

@@ -7,9 +7,10 @@ The changelog for SRS.
<a name="v7-changes"></a>
## SRS 7.0 Changelog
* v7.0, 2025-10-26, Build: Improve dependency checking to report all missing dependencies at once. v7.0.105 (#4293)
* v7.0, 2025-10-26, HLS: Support hls_master_m3u8_path_relative for reverse proxy compatibility. v7.0.104 (#4338)
* v7.0, 2025-10-25, API: Remove minimum limit of 10 for count parameter in /api/v1/streams and /api/v1/clients. v7.0.103 (#4358)
* v7.0, 2025-10-26, AI: WebRTC: Fix camera/microphone not released after closing publisher. v7.0.106 (#4261)
* v7.0, 2025-10-26, AI: Build: Improve dependency checking to report all missing dependencies at once. v7.0.105 (#4293)
* v7.0, 2025-10-26, AI: HLS: Support hls_master_m3u8_path_relative for reverse proxy compatibility. v7.0.104 (#4338)
* v7.0, 2025-10-25, AI: API: Remove minimum limit of 10 for count parameter in /api/v1/streams and /api/v1/clients. v7.0.103 (#4358)
* v7.0, 2025-10-22, AI: Only support AAC/MP3/Opus audio codec. v7.0.102 (#4516)
* v7.0, 2025-10-22, AI: Fix AAC audio sample rate reporting in API. v7.0.101 (#4518)
* v7.0, 2025-10-20, Merge [#4537](https://github.com/ossrs/srs/pull/4537): Forward: Reject RTMPS destinations with clear error message. v7.0.100 (#4537)

View File

@@ -28,6 +28,9 @@ function SrsRtcPublisherAsync() {
}
};
// Store media stream to stop tracks when closing.
self.userStream = null;
// @see https://github.com/rtcdn/rtcdn-draft
// @url The WebRTC url to play with, for example:
// webrtc://r.ossrs.net/live/livestream
@@ -60,10 +63,10 @@ function SrsRtcPublisherAsync() {
if (!navigator.mediaDevices && window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {
throw new SrsError('HttpsRequiredError', `Please use HTTPS or localhost to publish, read https://github.com/ossrs/srs/issues/2762#issuecomment-983147576`);
}
var stream = await navigator.mediaDevices.getUserMedia(self.constraints);
self.userStream = await navigator.mediaDevices.getUserMedia(self.constraints);
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
stream.getTracks().forEach(function (track) {
self.userStream.getTracks().forEach(function (track) {
self.pc.addTrack(track);
// Notify about local track when stream is ok.
@@ -104,6 +107,14 @@ function SrsRtcPublisherAsync() {
self.close = function () {
self.pc && self.pc.close();
self.pc = null;
// Stop all media tracks to release camera/microphone.
if (self.userStream) {
self.userStream.getTracks().forEach(function (track) {
track.stop();
});
self.userStream = null;
}
};
// The callback when got local stream.
@@ -523,6 +534,10 @@ function SrsRtcWhipWhepAsync() {
}
};
// Store media streams to stop tracks when closing.
self.displayStream = null;
self.userStream = null;
// See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
// @url The WebRTC url to publish with, for example:
// http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream
@@ -557,11 +572,11 @@ function SrsRtcWhipWhepAsync() {
}
if (useScreen) {
const displayStream = await navigator.mediaDevices.getDisplayMedia({
self.displayStream = await navigator.mediaDevices.getDisplayMedia({
video: true
});
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
displayStream.getTracks().forEach(function (track) {
self.displayStream.getTracks().forEach(function (track) {
self.pc.addTrack(track);
// Notify about local track when stream is ok.
self.ontrack && self.ontrack({track: track});
@@ -569,9 +584,9 @@ function SrsRtcWhipWhepAsync() {
}
if (useCamera || hasAudio) {
const userStream = await navigator.mediaDevices.getUserMedia(self.constraints);
self.userStream = await navigator.mediaDevices.getUserMedia(self.constraints);
userStream.getTracks().forEach(function (track) {
self.userStream.getTracks().forEach(function (track) {
self.pc.addTrack(track);
// Notify about local track when stream is ok.
self.ontrack && self.ontrack({track: track});
@@ -643,6 +658,20 @@ function SrsRtcWhipWhepAsync() {
self.close = function () {
self.pc && self.pc.close();
self.pc = null;
// Stop all media tracks to release camera/microphone.
if (self.displayStream) {
self.displayStream.getTracks().forEach(function (track) {
track.stop();
});
self.displayStream = null;
}
if (self.userStream) {
self.userStream.getTracks().forEach(function (track) {
track.stop();
});
self.userStream = null;
}
};
// The callback when got local stream.

View File

@@ -53,6 +53,7 @@
URL:
<input type="text" id="txt_url" class="input-xxlarge" value="">
<button class="btn btn-primary" id="btn_play">Play</button>
<button class="btn btn-danger" id="btn_stop" disabled>Stop</button>
</div>
<p></p>
@@ -130,6 +131,9 @@ $(function(){
}).then(function(session){
$('#sessionid').html(session.sessionid);
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
// Enable stop button after successful play
$('#btn_stop').prop('disabled', false);
$('#btn_play').prop('disabled', true);
}).catch(function (reason) {
sdk.close();
$('#rtc_media_player').hide();
@@ -137,11 +141,28 @@ $(function(){
});
};
var stopPlay = function() {
if (sdk) {
sdk.close();
if (statsTimer) {
clearInterval(statsTimer);
statsTimer = null;
}
$('#btn_stop').prop('disabled', true);
$('#btn_play').prop('disabled', false);
$('#sessionid').html('(stopped)');
$('#rtc_media_player').hide();
}
};
$('#rtc_media_player').hide();
var query = parse_query_string();
srs_init_whep("#txt_url", query);
$("#btn_play").click(startPlay);
$("#btn_stop").click(stopPlay);
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
if (query.autostart === 'true') {
$('#rtc_media_player').prop('muted', true);

View File

@@ -53,6 +53,7 @@
URL:
<input type="text" id="txt_url" class="input-xxlarge" value="">
<button class="btn btn-primary" id="btn_publish">Publish</button>
<button class="btn btn-danger" id="btn_stop" disabled>Stop</button>
</div>
<p></p>
@@ -138,6 +139,9 @@ $(function(){
}).then(function(session){
$('#sessionid').html(session.sessionid);
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
// Enable stop button after successful publish
$('#btn_stop').prop('disabled', false);
$('#btn_publish').prop('disabled', true);
}).catch(function (reason) {
// Throw by sdk.
if (reason instanceof SrsError) {
@@ -164,11 +168,29 @@ $(function(){
});
};
var stopPublish = function() {
if (sdk) {
sdk.close();
if (statsTimer) {
clearInterval(statsTimer);
statsTimer = null;
}
$('#btn_stop').prop('disabled', true);
$('#btn_publish').prop('disabled', false);
$('#sessionid').html('(stopped)');
$('#rtc_media_player').hide();
console.log('PeerConnection closed. Check if camera indicator is still on!');
}
};
$('#rtc_media_player').hide();
var query = parse_query_string();
srs_init_whip("#txt_url", query);
$("#btn_publish").click(startPublish);
$("#btn_stop").click(stopPublish);
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
if (query.autostart === 'true') {
window.addEventListener("load", function(){ startPublish(); });

View File

@@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
#define VERSION_REVISION 105
#define VERSION_REVISION 106
#endif