mirror of
https://github.com/ossrs/srs.git
synced 2025-02-12 19:31:53 +00:00
Support WHIP and WHEP player. v5.0.147 and v6.0.35 (#3460)
Co-authored-by: chundonglinlin <chundonglinlin@163.com> Co-authored-by: panda <542638787@qq.com>
This commit is contained in:
parent
5067e220ca
commit
c001acaae9
12 changed files with 456 additions and 10 deletions
|
@ -8,6 +8,7 @@ The changelog for SRS.
|
|||
|
||||
## SRS 6.0 Changelog
|
||||
|
||||
* v6.0, 2023-03-20, Merge [#3460](https://github.com/ossrs/srs/pull/3460): WebRTC: Support WHIP/WHEP players. v6.0.35 (#3460)
|
||||
* v6.0, 2023-03-07, Merge [#3441](https://github.com/ossrs/srs/pull/3441): HEVC: webrtc support hevc on safari. v6.0.34 (#3441)
|
||||
* v6.0, 2023-03-07, Merge [#3446](https://github.com/ossrs/srs/pull/3446): WebRTC: Warning if no ideal profile. v6.0.33 (#3446)
|
||||
* v6.0, 2023-03-06, Merge [#3445](https://github.com/ossrs/srs/pull/3445): Support configure for generic linux. v6.0.32 (#3445)
|
||||
|
@ -48,6 +49,7 @@ The changelog for SRS.
|
|||
|
||||
## SRS 5.0 Changelog
|
||||
|
||||
* v5.0, 2023-03-20, Merge [#3460](https://github.com/ossrs/srs/pull/3460): WebRTC: Support WHIP/WHEP players. v5.0.147 (#3460)
|
||||
* v5.0, 2023-03-07, Merge [#3446](https://github.com/ossrs/srs/pull/3446): WebRTC: Warning if no ideal profile. v5.0.146 (#3446)
|
||||
* v5.0, 2023-03-06, Merge [#3445](https://github.com/ossrs/srs/pull/3445): Support configure for generic linux. v5.0.145 (#3445)
|
||||
* v5.0, 2023-03-04, Merge [#3105](https://github.com/ossrs/srs/pull/3105): Kickoff publisher when stream is idle, which means no players. v5.0.144 (#3105)
|
||||
|
|
|
@ -74,6 +74,7 @@ The features of SRS.
|
|||
- [x] Other: [Experimental] Support pushing MPEG-TS over UDP, please read [bug #250](https://github.com/ossrs/srs/issues/250). v2.0.111+
|
||||
- [x] Other: [Experimental] Support pushing FLV over HTTP POST, please read wiki([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/streamer#push-http-flv-to-srs), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/streamer#push-http-flv-to-srs)). v2.0.163+
|
||||
- [x] Other: [Experimental] Support push stream by GB28181, [#3176](https://github.com/ossrs/srs/issues/3176). v5.0.74+
|
||||
- [x] Other: Support WHIP/WHEP player, [#3460](https://github.com/ossrs/srs/pull/3460). v5.0.147+
|
||||
- [ ] System: Proxy to extend origin servers, [#3138](https://github.com/ossrs/srs/issues/3138).
|
||||
- [ ] System: Support source cleanup for idle streams, [#413](https://github.com/ossrs/srs/issues/413).
|
||||
- [ ] System: Support JT808 and JT1708 for transport, [#3420](https://github.com/ossrs/srs/issues/3420).
|
||||
|
|
|
@ -17,6 +17,8 @@ function update_nav() {
|
|||
$("#nav_srs_player").attr("href", "srs_player.html" + window.location.search);
|
||||
$("#nav_rtc_player").attr("href", "rtc_player.html" + window.location.search);
|
||||
$("#nav_rtc_publisher").attr("href", "rtc_publisher.html" + window.location.search);
|
||||
$("#nav_whip").attr("href", "whip.html" + window.location.search);
|
||||
$("#nav_whep").attr("href", "whep.html" + window.location.search);
|
||||
$("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search);
|
||||
$("#nav_srs_chat").attr("href", "srs_chat.html" + window.location.search);
|
||||
$("#nav_srs_bwt").attr("href", "srs_bwt.html" + window.location.search);
|
||||
|
@ -116,6 +118,38 @@ function build_default_rtc_url(query) {
|
|||
return uri;
|
||||
};
|
||||
|
||||
function build_default_whip_whep_url(query, apiPath) {
|
||||
// The format for query string to overwrite configs of server.
|
||||
console.log('?eip=x.x.x.x to overwrite candidate. 覆盖服务器candidate(外网IP)配置');
|
||||
console.log('?api=x to overwrite WebRTC API(1985).');
|
||||
console.log('?schema=http|https to overwrite WebRTC API protocol.');
|
||||
|
||||
var server = (!query.server)? window.location.hostname:query.server;
|
||||
var vhost = (!query.vhost)? window.location.hostname:query.vhost;
|
||||
var app = (!query.app)? "live":query.app;
|
||||
var stream = (!query.stream)? "livestream":query.stream;
|
||||
var api = ':' + (query.api || (window.location.protocol === 'http:' ? '1985' : '1990'));
|
||||
|
||||
var queries = [];
|
||||
if (server !== vhost && vhost !== "__defaultVhost__") {
|
||||
queries.push("vhost=" + vhost);
|
||||
}
|
||||
if (query.schema && window.location.protocol !== query.schema + ':') {
|
||||
queries.push('schema=' + query.schema);
|
||||
}
|
||||
queries = user_extra_params(query, queries, true);
|
||||
|
||||
var uri = window.location.protocol + "//" + server + api + apiPath + "?app=" + app + "&stream=" + stream + "&" + queries.join('&');
|
||||
while (uri.lastIndexOf("?") === uri.length - 1) {
|
||||
uri = uri.slice(0, uri.length - 1);
|
||||
}
|
||||
while (uri.lastIndexOf("&") === uri.length - 1) {
|
||||
uri = uri.slice(0, uri.length - 1);
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the page.
|
||||
* @param flv_url the div id contains the flv stream url to play
|
||||
|
@ -136,3 +170,11 @@ function srs_init_rtc(id, query) {
|
|||
update_nav();
|
||||
$(id).val(build_default_rtc_url(query));
|
||||
}
|
||||
function srs_init_whip(id, query) {
|
||||
update_nav();
|
||||
$(id).val(build_default_whip_whep_url(query, '/rtc/v1/whip/'));
|
||||
}
|
||||
function srs_init_whep(id, query) {
|
||||
update_nav();
|
||||
$(id).val(build_default_whip_whep_url(query, '/rtc/v1/whip-play/'));
|
||||
}
|
||||
|
|
|
@ -134,14 +134,14 @@ function SrsRtcPublisherAsync() {
|
|||
api += '/';
|
||||
}
|
||||
|
||||
apiUrl = schema + '//' + urlObject.server + ':' + port + api;
|
||||
var apiUrl = schema + '//' + urlObject.server + ':' + port + api;
|
||||
for (var key in urlObject.user_query) {
|
||||
if (key !== 'api' && key !== 'play') {
|
||||
apiUrl += '&' + key + '=' + urlObject.user_query[key];
|
||||
}
|
||||
}
|
||||
// Replace /rtc/v1/play/&k=v to /rtc/v1/play/?k=v
|
||||
var apiUrl = apiUrl.replace(api + '&', api + '?');
|
||||
apiUrl = apiUrl.replace(api + '&', api + '?');
|
||||
|
||||
var streamUrl = urlObject.url;
|
||||
|
||||
|
@ -369,14 +369,14 @@ function SrsRtcPlayerAsync() {
|
|||
api += '/';
|
||||
}
|
||||
|
||||
apiUrl = schema + '//' + urlObject.server + ':' + port + api;
|
||||
var apiUrl = schema + '//' + urlObject.server + ':' + port + api;
|
||||
for (var key in urlObject.user_query) {
|
||||
if (key !== 'api' && key !== 'play') {
|
||||
apiUrl += '&' + key + '=' + urlObject.user_query[key];
|
||||
}
|
||||
}
|
||||
// Replace /rtc/v1/play/&k=v to /rtc/v1/play/?k=v
|
||||
var apiUrl = apiUrl.replace(api + '&', api + '?');
|
||||
apiUrl = apiUrl.replace(api + '&', api + '?');
|
||||
|
||||
var streamUrl = urlObject.url;
|
||||
|
||||
|
@ -510,6 +510,145 @@ function SrsRtcPlayerAsync() {
|
|||
return self;
|
||||
}
|
||||
|
||||
// Depends on adapter-7.4.0.min.js from https://github.com/webrtc/adapter
|
||||
// Async-awat-prmise based SRS RTC Publisher by WHIP.
|
||||
function SrsRtcWhipWhepAsync() {
|
||||
var self = {};
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
||||
self.constraints = {
|
||||
audio: true,
|
||||
video: {
|
||||
width: {ideal: 320, max: 576}
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
self.publish = async function (url) {
|
||||
if (url.indexOf('/whip/') === -1) throw new Error(`invalid WHIP url ${url}`);
|
||||
|
||||
self.pc.addTransceiver("audio", {direction: "sendonly"});
|
||||
self.pc.addTransceiver("video", {direction: "sendonly"});
|
||||
|
||||
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);
|
||||
|
||||
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
|
||||
stream.getTracks().forEach(function (track) {
|
||||
self.pc.addTrack(track);
|
||||
|
||||
// Notify about local track when stream is ok.
|
||||
self.ontrack && self.ontrack({track: track});
|
||||
});
|
||||
|
||||
var offer = await self.pc.createOffer();
|
||||
await self.pc.setLocalDescription(offer);
|
||||
const answer = await new Promise(function (resolve, reject) {
|
||||
console.log("Generated offer: ", offer);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
const data = xhr.responseText;
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
}
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-type', 'application/sdp');
|
||||
xhr.send(offer.sdp);
|
||||
});
|
||||
await self.pc.setRemoteDescription(
|
||||
new RTCSessionDescription({type: 'answer', sdp: answer})
|
||||
);
|
||||
|
||||
return self.__internal.parseId(url, offer.sdp, answer);
|
||||
};
|
||||
|
||||
// See https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
|
||||
// @url The WebRTC url to play with, for example:
|
||||
// http://localhost:1985/rtc/v1/whip-play/?app=live&stream=livestream
|
||||
self.play = async function(url) {
|
||||
if (url.indexOf('/whip-play/') === -1 && url.indexOf('/whep/') === -1) throw new Error(`invalid WHEP url ${url}`);
|
||||
|
||||
self.pc.addTransceiver("audio", {direction: "recvonly"});
|
||||
self.pc.addTransceiver("video", {direction: "recvonly"});
|
||||
|
||||
var offer = await self.pc.createOffer();
|
||||
await self.pc.setLocalDescription(offer);
|
||||
const answer = await new Promise(function(resolve, reject) {
|
||||
console.log("Generated offer: ", offer);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onload = function() {
|
||||
if (xhr.readyState !== xhr.DONE) return;
|
||||
if (xhr.status !== 200) return reject(xhr);
|
||||
const data = xhr.responseText;
|
||||
console.log("Got answer: ", data);
|
||||
return data.code ? reject(xhr) : resolve(data);
|
||||
}
|
||||
xhr.open('POST', url, true);
|
||||
xhr.setRequestHeader('Content-type', 'application/sdp');
|
||||
xhr.send(offer.sdp);
|
||||
});
|
||||
await self.pc.setRemoteDescription(
|
||||
new RTCSessionDescription({type: 'answer', sdp: answer})
|
||||
);
|
||||
|
||||
return self.__internal.parseId(url, offer.sdp, answer);
|
||||
};
|
||||
|
||||
// Close the publisher.
|
||||
self.close = function () {
|
||||
self.pc && self.pc.close();
|
||||
self.pc = null;
|
||||
};
|
||||
|
||||
// The callback when got local stream.
|
||||
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
|
||||
self.ontrack = function (event) {
|
||||
// Add track to stream of SDK.
|
||||
self.stream.addTrack(event.track);
|
||||
};
|
||||
|
||||
self.pc = new RTCPeerConnection(null);
|
||||
|
||||
// To keep api consistent between player and publisher.
|
||||
// @see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream#Migrating_to_addTrack
|
||||
// @see https://webrtc.org/getting-started/media-devices
|
||||
self.stream = new MediaStream();
|
||||
|
||||
// Internal APIs.
|
||||
self.__internal = {
|
||||
parseId: (url, offer, answer) => {
|
||||
let sessionid = offer.substr(offer.indexOf('a=ice-ufrag:') + 'a=ice-ufrag:'.length);
|
||||
sessionid = sessionid.substr(0, sessionid.indexOf('\n') - 1) + ':';
|
||||
sessionid += answer.substr(answer.indexOf('a=ice-ufrag:') + 'a=ice-ufrag:'.length);
|
||||
sessionid = sessionid.substr(0, sessionid.indexOf('\n'));
|
||||
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
return {
|
||||
sessionid: sessionid, // Should be ice-ufrag of answer:offer.
|
||||
simulator: a.protocol + '//' + a.host + '/rtc/v1/nack/',
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/ontrack
|
||||
self.pc.ontrack = function(event) {
|
||||
if (self.ontrack) {
|
||||
self.ontrack(event);
|
||||
}
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Format the codec of RTCRtpSender, kind(audio/video) is optional filter.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#getting_the_supported_codecs
|
||||
function SrsRtcFormatSenders(senders, kind) {
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li class="active"><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
|
||||
<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
|
||||
<li><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||||
<li><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||||
|
@ -105,8 +107,7 @@ $(function(){
|
|||
$('#rtc_media_player').prop('muted', true);
|
||||
console.warn('For autostart, we should mute it, see https://www.jianshu.com/p/c3c6944eed5a ' +
|
||||
'or https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#audiovideo_elements');
|
||||
|
||||
startPlay();
|
||||
window.addEventListener("load", function(){ startPlay(); });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
|
||||
<li class="active"><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
|
||||
<li><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||||
<li><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<li class="active"><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
|
||||
<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
|
||||
<li><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||||
<li><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||||
|
|
114
trunk/research/players/whep.html
Normal file
114
trunk/research/players/whep.html
Normal file
|
@ -0,0 +1,114 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SRS</title>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body{
|
||||
padding-top: 30px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
|
||||
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
|
||||
<script type="text/javascript" src="js/adapter-7.4.0.min.js"></script>
|
||||
<script type="text/javascript" src="js/srs.sdk.js"></script>
|
||||
<script type="text/javascript" src="js/winlin.utility.js"></script>
|
||||
<script type="text/javascript" src="js/srs.page.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<img src='//ossrs.net/gif/v1/sls.gif?site=ossrs.net&path=/player/rtcpublisher'/>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a id="srs_index" class="brand" href="https://github.com/ossrs/srs">SRS</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
|
||||
<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
|
||||
<li><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||||
<li class="active"><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||||
<!--<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>-->
|
||||
<!--<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>-->
|
||||
<!--<li><a id="nav_gb28181" href="srs_gb28181.html">GB28181</a></li>-->
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs">
|
||||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs?style=social">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="form-inline">
|
||||
URL:
|
||||
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
||||
<button class="btn btn-primary" id="btn_play">Play</button>
|
||||
</div>
|
||||
|
||||
<label></label>
|
||||
<video id="rtc_media_player" width="320" autoplay muted></video>
|
||||
|
||||
<label></label>
|
||||
SessionID: <span id='sessionid'></span>
|
||||
|
||||
<label></label>
|
||||
Simulator: <a href='#' id='simulator-drop'>Drop</a>
|
||||
|
||||
<footer>
|
||||
<p></p>
|
||||
<p><a href="https://github.com/ossrs/srs">SRS Team © 2020</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
var sdk = null; // Global handler to do cleanup when republishing.
|
||||
var startPlay = function() {
|
||||
$('#rtc_media_player').show();
|
||||
|
||||
// Close PC when user replay.
|
||||
if (sdk) {
|
||||
sdk.close();
|
||||
}
|
||||
sdk = new SrsRtcWhipWhepAsync();
|
||||
|
||||
// User should set the stream when publish is done, @see https://webrtc.org/getting-started/media-devices
|
||||
// However SRS SDK provides a consist API like https://webrtc.org/getting-started/remote-streams
|
||||
$('#rtc_media_player').prop('srcObject', sdk.stream);
|
||||
// Optional callback, SDK will add track to stream.
|
||||
// sdk.ontrack = function (event) { console.log('Got track', event); sdk.stream.addTrack(event.track); };
|
||||
|
||||
// For example: webrtc://r.ossrs.net/live/livestream
|
||||
var url = $("#txt_url").val();
|
||||
sdk.play(url).then(function(session){
|
||||
$('#sessionid').html(session.sessionid);
|
||||
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
|
||||
}).catch(function (reason) {
|
||||
sdk.close();
|
||||
$('#rtc_media_player').hide();
|
||||
console.error(reason);
|
||||
});
|
||||
};
|
||||
|
||||
$('#rtc_media_player').hide();
|
||||
var query = parse_query_string();
|
||||
srs_init_whep("#txt_url", query);
|
||||
|
||||
$("#btn_play").click(startPlay);
|
||||
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
||||
if (query.autostart === 'true') {
|
||||
$('#rtc_media_player').prop('muted', true);
|
||||
console.warn('For autostart, we should mute it, see https://www.jianshu.com/p/c3c6944eed5a ' +
|
||||
'or https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#audiovideo_elements');
|
||||
window.addEventListener("load", function(){ startPlay(); });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
142
trunk/research/players/whip.html
Normal file
142
trunk/research/players/whip.html
Normal file
|
@ -0,0 +1,142 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SRS</title>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body{
|
||||
padding-top: 30px;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
|
||||
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
|
||||
<script type="text/javascript" src="js/adapter-7.4.0.min.js"></script>
|
||||
<script type="text/javascript" src="js/srs.sdk.js"></script>
|
||||
<script type="text/javascript" src="js/winlin.utility.js"></script>
|
||||
<script type="text/javascript" src="js/srs.page.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<img src='//ossrs.net/gif/v1/sls.gif?site=ossrs.net&path=/player/rtcpublisher'/>
|
||||
<div class="navbar navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<a id="srs_index" class="brand" href="https://github.com/ossrs/srs">SRS</a>
|
||||
<div class="nav-collapse collapse">
|
||||
<ul class="nav">
|
||||
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
||||
<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
|
||||
<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
|
||||
<li class="active"><a id="nav_whip" href="whip.html">WHIP</a></li>
|
||||
<li><a id="nav_whep" href="whip.html">WHEP</a></li>
|
||||
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
|
||||
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
|
||||
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
|
||||
<!--<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>-->
|
||||
<!--<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>-->
|
||||
<!--<li><a id="nav_gb28181" href="srs_gb28181.html">GB28181</a></li>-->
|
||||
<li>
|
||||
<a href="https://github.com/ossrs/srs">
|
||||
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs?style=social">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="form-inline">
|
||||
URL:
|
||||
<input type="text" id="txt_url" class="input-xxlarge" value="">
|
||||
<button class="btn btn-primary" id="btn_publish">Publish</button>
|
||||
</div>
|
||||
|
||||
<label></label>
|
||||
<video id="rtc_media_player" width="320" autoplay muted></video>
|
||||
|
||||
<label></label>
|
||||
SessionID: <span id='sessionid'></span>
|
||||
|
||||
<label></label>
|
||||
Audio: <span id='acodecs'></span><br/>
|
||||
Video: <span id='vcodecs'></span>
|
||||
|
||||
<label></label>
|
||||
Simulator: <a href='#' id='simulator-drop'>Drop</a>
|
||||
|
||||
<footer>
|
||||
<p></p>
|
||||
<p><a href="https://github.com/ossrs/srs">SRS Team © 2020</a></p>
|
||||
</footer>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
var sdk = null; // Global handler to do cleanup when republishing.
|
||||
var startPublish = function() {
|
||||
$('#rtc_media_player').show();
|
||||
|
||||
// Close PC when user replay.
|
||||
if (sdk) {
|
||||
sdk.close();
|
||||
}
|
||||
sdk = new SrsRtcWhipWhepAsync();
|
||||
|
||||
// User should set the stream when publish is done, @see https://webrtc.org/getting-started/media-devices
|
||||
// However SRS SDK provides a consist API like https://webrtc.org/getting-started/remote-streams
|
||||
$('#rtc_media_player').prop('srcObject', sdk.stream);
|
||||
// Optional callback, SDK will add track to stream.
|
||||
// sdk.ontrack = function (event) { console.log('Got track', event); sdk.stream.addTrack(event.track); };
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/WebRTC_codecs#getting_the_supported_codecs
|
||||
sdk.pc.onicegatheringstatechange = function (event) {
|
||||
if (sdk.pc.iceGatheringState === "complete") {
|
||||
$('#acodecs').html(SrsRtcFormatSenders(sdk.pc.getSenders(), "audio"));
|
||||
$('#vcodecs').html(SrsRtcFormatSenders(sdk.pc.getSenders(), "video"));
|
||||
}
|
||||
};
|
||||
|
||||
// For example: webrtc://r.ossrs.net/live/livestream
|
||||
var url = $("#txt_url").val();
|
||||
sdk.publish(url).then(function(session){
|
||||
$('#sessionid').html(session.sessionid);
|
||||
$('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
|
||||
}).catch(function (reason) {
|
||||
// Throw by sdk.
|
||||
if (reason instanceof SrsError) {
|
||||
if (reason.name === 'HttpsRequiredError') {
|
||||
alert(`WebRTC推流必须是HTTPS或者localhost:${reason.name} ${reason.message}`);
|
||||
} else {
|
||||
alert(`${reason.name} ${reason.message}`);
|
||||
}
|
||||
}
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#exceptions
|
||||
if (reason instanceof DOMException) {
|
||||
if (reason.name === 'NotFoundError') {
|
||||
alert(`找不到麦克风和摄像头设备:getUserMedia ${reason.name} ${reason.message}`);
|
||||
} else if (reason.name === 'NotAllowedError') {
|
||||
alert(`你禁止了网页访问摄像头和麦克风:getUserMedia ${reason.name} ${reason.message}`);
|
||||
} else if (['AbortError', 'NotAllowedError', 'NotFoundError', 'NotReadableError', 'OverconstrainedError', 'SecurityError', 'TypeError'].includes(reason.name)) {
|
||||
alert(`getUserMedia ${reason.name} ${reason.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
sdk.close();
|
||||
$('#rtc_media_player').hide();
|
||||
console.error(reason);
|
||||
});
|
||||
};
|
||||
|
||||
$('#rtc_media_player').hide();
|
||||
var query = parse_query_string();
|
||||
srs_init_whip("#txt_url", query);
|
||||
|
||||
$("#btn_publish").click(startPublish);
|
||||
// Never play util windows loaded @see https://github.com/ossrs/srs/issues/2732
|
||||
if (query.autostart === 'true') {
|
||||
window.addEventListener("load", function(){ startPublish(); });
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -638,6 +638,7 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
|||
ruc.req_->vhost = ruc.req_->host;
|
||||
ruc.req_->app = app.empty() ? "live" : app;
|
||||
ruc.req_->stream = stream.empty() ? "livestream" : stream;
|
||||
ruc.req_->param = r->query();
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective* parsed_vhost = _srs_config->get_vhost(ruc.req_->vhost);
|
||||
|
@ -645,9 +646,9 @@ srs_error_t SrsGoApiRtcWhip::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa
|
|||
ruc.req_->vhost = parsed_vhost->arg0();
|
||||
}
|
||||
|
||||
srs_trace("RTC whip %s %s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, codec=%s",
|
||||
srs_trace("RTC whip %s %s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, codec=%s, param=%s",
|
||||
action.c_str(), ruc.req_->get_stream_url().c_str(), clientip.c_str(), ruc.req_->app.c_str(), ruc.req_->stream.c_str(),
|
||||
remote_sdp_str.length(), eip.c_str(), codec.c_str()
|
||||
remote_sdp_str.length(), eip.c_str(), codec.c_str(), ruc.req_->param.c_str()
|
||||
);
|
||||
|
||||
ruc.eip_ = eip;
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 146
|
||||
#define VERSION_REVISION 147
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 6
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 34
|
||||
#define VERSION_REVISION 35
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue