AI: WebRTC: Fix camera/microphone not released after closing publisher. v7.0.106 (#4261)
This commit is contained in:
parent
9eae868e91
commit
51ab6403a3
|
|
@ -7,9 +7,10 @@ The changelog for SRS.
|
||||||
<a name="v7-changes"></a>
|
<a name="v7-changes"></a>
|
||||||
|
|
||||||
## SRS 7.0 Changelog
|
## 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, AI: WebRTC: Fix camera/microphone not released after closing publisher. v7.0.106 (#4261)
|
||||||
* v7.0, 2025-10-26, HLS: Support hls_master_m3u8_path_relative for reverse proxy compatibility. v7.0.104 (#4338)
|
* 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-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: 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: 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-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)
|
* 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)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ function SrsRtcPublisherAsync() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Store media stream to stop tracks when closing.
|
||||||
|
self.userStream = null;
|
||||||
|
|
||||||
// @see https://github.com/rtcdn/rtcdn-draft
|
// @see https://github.com/rtcdn/rtcdn-draft
|
||||||
// @url The WebRTC url to play with, for example:
|
// @url The WebRTC url to play with, for example:
|
||||||
// webrtc://r.ossrs.net/live/livestream
|
// webrtc://r.ossrs.net/live/livestream
|
||||||
|
|
@ -60,10 +63,10 @@ function SrsRtcPublisherAsync() {
|
||||||
if (!navigator.mediaDevices && window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {
|
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`);
|
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
|
// @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);
|
self.pc.addTrack(track);
|
||||||
|
|
||||||
// Notify about local track when stream is ok.
|
// Notify about local track when stream is ok.
|
||||||
|
|
@ -104,6 +107,14 @@ function SrsRtcPublisherAsync() {
|
||||||
self.close = function () {
|
self.close = function () {
|
||||||
self.pc && self.pc.close();
|
self.pc && self.pc.close();
|
||||||
self.pc = null;
|
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.
|
// 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/
|
// See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
|
||||||
// @url The WebRTC url to publish with, for example:
|
// @url The WebRTC url to publish with, for example:
|
||||||
// http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream
|
// http://localhost:1985/rtc/v1/whip/?app=live&stream=livestream
|
||||||
|
|
@ -557,11 +572,11 @@ function SrsRtcWhipWhepAsync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useScreen) {
|
if (useScreen) {
|
||||||
const displayStream = await navigator.mediaDevices.getDisplayMedia({
|
self.displayStream = await navigator.mediaDevices.getDisplayMedia({
|
||||||
video: true
|
video: true
|
||||||
});
|
});
|
||||||
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
|
// @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);
|
self.pc.addTrack(track);
|
||||||
// Notify about local track when stream is ok.
|
// Notify about local track when stream is ok.
|
||||||
self.ontrack && self.ontrack({track: track});
|
self.ontrack && self.ontrack({track: track});
|
||||||
|
|
@ -569,9 +584,9 @@ function SrsRtcWhipWhepAsync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useCamera || hasAudio) {
|
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);
|
self.pc.addTrack(track);
|
||||||
// Notify about local track when stream is ok.
|
// Notify about local track when stream is ok.
|
||||||
self.ontrack && self.ontrack({track: track});
|
self.ontrack && self.ontrack({track: track});
|
||||||
|
|
@ -643,6 +658,20 @@ function SrsRtcWhipWhepAsync() {
|
||||||
self.close = function () {
|
self.close = function () {
|
||||||
self.pc && self.pc.close();
|
self.pc && self.pc.close();
|
||||||
self.pc = null;
|
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.
|
// The callback when got local stream.
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
URL:
|
URL:
|
||||||
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
||||||
<button class="btn btn-primary" id="btn_play">Play</button>
|
<button class="btn btn-primary" id="btn_play">Play</button>
|
||||||
|
<button class="btn btn-danger" id="btn_stop" disabled>Stop</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
@ -130,6 +131,9 @@ $(function(){
|
||||||
}).then(function(session){
|
}).then(function(session){
|
||||||
$('#sessionid').html(session.sessionid);
|
$('#sessionid').html(session.sessionid);
|
||||||
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + 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) {
|
}).catch(function (reason) {
|
||||||
sdk.close();
|
sdk.close();
|
||||||
$('#rtc_media_player').hide();
|
$('#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();
|
$('#rtc_media_player').hide();
|
||||||
var query = parse_query_string();
|
var query = parse_query_string();
|
||||||
srs_init_whep("#txt_url", query);
|
srs_init_whep("#txt_url", query);
|
||||||
|
|
||||||
$("#btn_play").click(startPlay);
|
$("#btn_play").click(startPlay);
|
||||||
|
$("#btn_stop").click(stopPlay);
|
||||||
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
||||||
if (query.autostart === 'true') {
|
if (query.autostart === 'true') {
|
||||||
$('#rtc_media_player').prop('muted', true);
|
$('#rtc_media_player').prop('muted', true);
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
URL:
|
URL:
|
||||||
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
||||||
<button class="btn btn-primary" id="btn_publish">Publish</button>
|
<button class="btn btn-primary" id="btn_publish">Publish</button>
|
||||||
|
<button class="btn btn-danger" id="btn_stop" disabled>Stop</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
@ -138,6 +139,9 @@ $(function(){
|
||||||
}).then(function(session){
|
}).then(function(session){
|
||||||
$('#sessionid').html(session.sessionid);
|
$('#sessionid').html(session.sessionid);
|
||||||
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + 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) {
|
}).catch(function (reason) {
|
||||||
// Throw by sdk.
|
// Throw by sdk.
|
||||||
if (reason instanceof SrsError) {
|
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();
|
$('#rtc_media_player').hide();
|
||||||
var query = parse_query_string();
|
var query = parse_query_string();
|
||||||
srs_init_whip("#txt_url", query);
|
srs_init_whip("#txt_url", query);
|
||||||
|
|
||||||
$("#btn_publish").click(startPublish);
|
$("#btn_publish").click(startPublish);
|
||||||
|
$("#btn_stop").click(stopPublish);
|
||||||
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
||||||
if (query.autostart === 'true') {
|
if (query.autostart === 'true') {
|
||||||
window.addEventListener("load", function(){ startPublish(); });
|
window.addEventListener("load", function(){ startPublish(); });
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
#define VERSION_MAJOR 7
|
#define VERSION_MAJOR 7
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 105
|
#define VERSION_REVISION 106
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Loading…
Reference in New Issue
Block a user