Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support webrtc-datachannel sdp exchange #3475

Draft
wants to merge 14 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ on:
tags:
- v6*

# Declare default permissions as read only.
permissions: read-all
# For draft, need write permission.
permissions:
contents: write

jobs:
envs:
Expand Down Expand Up @@ -284,6 +285,7 @@ jobs:
needs:
- envs
- docker-srs
- test
steps:
##################################################################################################################
- name: Covert output to env
Expand Down
3 changes: 2 additions & 1 deletion trunk/auto/depends.sh
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,8 @@ if [[ $SRS_RTC == YES && $SRS_FFMPEG_OPUS != YES ]]; then
rm -rf ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 ${SRS_OBJS}/${SRS_PLATFORM}/3rdpatry/opus ${SRS_OBJS}/opus &&
tar xf ${SRS_WORKDIR}/3rdparty/opus-1.3.1.tar.gz -C ${SRS_OBJS}/${SRS_PLATFORM} &&
(
cd ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 &&
# Opus requires automake 1.15, and fails for automake 1.16+, so we run autoreconf to fix it.
cd ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 && autoreconf &&
./configure --prefix=${SRS_DEPENDS_LIBS}/${SRS_PLATFORM}/3rdpatry/opus --enable-static $OPUS_OPTIONS
) &&
make -C ${SRS_OBJS}/${SRS_PLATFORM}/opus-1.3.1 ${SRS_JOBS} &&
Expand Down
8 changes: 8 additions & 0 deletions trunk/conf/hevc.flv.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
srt_server {
enabled on;
listen 10080;
}
http_api {
enabled on;
listen 1985;
Expand All @@ -11,6 +15,10 @@ http_server {
listen 8080;
}
vhost __defaultVhost__ {
srt {
enabled on;
srt_to_rtmp on;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
Expand Down
8 changes: 8 additions & 0 deletions trunk/conf/hevc.ts.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
srt_server {
enabled on;
listen 10080;
}
http_api {
enabled on;
listen 1985;
Expand All @@ -11,6 +15,10 @@ http_server {
listen 8080;
}
vhost __defaultVhost__ {
srt {
enabled on;
srt_to_rtmp on;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].ts;
Expand Down
2 changes: 1 addition & 1 deletion trunk/conf/realtime.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ max_connections 1000;
daemon off;
srs_log_tank console;
vhost __defaultVhost__ {
tcp_nodelay on
tcp_nodelay on;
min_latency on;

play {
Expand Down
2 changes: 1 addition & 1 deletion trunk/conf/realtime.flv.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ vhost __defaultVhost__ {
mount [vhost]/[app]/[stream].flv;
}

tcp_nodelay on
tcp_nodelay on;
min_latency on;

play {
Expand Down
10 changes: 10 additions & 0 deletions trunk/doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ The changelog for SRS.

## SRS 6.0 Changelog

* v6.0, 2023-03-27, Merge [#3450](https://github.com/ossrs/srs/pull/3450): WebRTC: Error message carries the SDP when failed. v6.0.39 (#3450)
* v6.0, 2023-03-25, Merge [#3477](https://github.com/ossrs/srs/pull/3477): Remove unneccessary NULL check in srs_freep. v6.0.38 (#3477)
* v6.0, 2023-03-25, Merge [#3455](https://github.com/ossrs/srs/pull/3455): RTC: Call on_play before create session, for it might be freed for timeout. v6.0.37 (#3455)
* v6.0, 2023-03-22, Merge [#3427](https://github.com/ossrs/srs/pull/3427): WHIP: Support DELETE resource for Larix Broadcaster. v6.0.36 (#3427)
* 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)
Expand Down Expand Up @@ -48,6 +53,11 @@ The changelog for SRS.

## SRS 5.0 Changelog

* v5.0, 2023-03-27, Merge [#3450](https://github.com/ossrs/srs/pull/3450): WebRTC: Error message carries the SDP when failed. v5.0.151 (#3450)
* v5.0, 2023-03-25, Merge [#3477](https://github.com/ossrs/srs/pull/3477): Remove unneccessary NULL check in srs_freep. v5.0.150 (#3477)
* v5.0, 2023-03-25, Merge [#3455](https://github.com/ossrs/srs/pull/3455): RTC: Call on_play before create session, for it might be freed for timeout. v5.0.149 (#3455)
* v5.0, 2023-03-22, Merge [#3427](https://github.com/ossrs/srs/pull/3427): WHIP: Support DELETE resource for Larix Broadcaster. v5.0.148 (#3427)
* 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)
Expand Down
2 changes: 2 additions & 0 deletions trunk/doc/Features.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ The features of SRS.
- [x] RTC: [Experimental] Support transmux RTC to RTMP, [#2093](https://github.com/ossrs/srs/issues/2093). v4.0.95
- [x] RTC: [Experimental] Support WebRTC over TCP directly, [#2852](https://github.com/ossrs/srs/issues/2852). v5.0.60+
- [x] RTC: [Experimental] Support WHIP(WebRTC-HTTP ingestion protocol), [#3170](https://github.com/ossrs/srs/issues/3170). v5.0.61+
- [x] RTC: [Experimental] Support [Larix Broadcaster](https://softvelum.com/larix/), [#3476](https://github.com/ossrs/srs/issues/3476). v5.0.148+
- [x] Other: Support ingesting([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/ingest), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/ingest)) other protocols to SRS by FFMPEG. v1.0.0+
- [x] Other: Support forwarding([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/forward), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/forward)) to other RTMP servers. v1.0.0+
- [x] Other: Support transcoding([CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/ffmpeg), [EN](https://ossrs.io/lts/en-us/docs/v4/doc/ffmpeg)) by FFMPEG. v1.0.0+
Expand All @@ -74,6 +75,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).
Expand Down
42 changes: 42 additions & 0 deletions trunk/research/players/js/srs.page.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not give ?a:b some spaces, ref line #131 'http:' ? '1985' : '1990'. They are so crowded, are they?

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
Expand All @@ -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/'));
}
151 changes: 145 additions & 6 deletions trunk/research/players/js/srs.sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function SrsRtcPublisherAsync() {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.readyState !== xhr.DONE) return;
if (xhr.status !== 200) return reject(xhr);
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
const data = JSON.parse(xhr.responseText);
console.log("Got answer: ", data);
return data.code ? reject(xhr) : resolve(data);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -318,7 +318,7 @@ function SrsRtcPlayerAsync() {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.readyState !== xhr.DONE) return;
if (xhr.status !== 200) return reject(xhr);
if (xhr.status !== 200 && xhr.status !== 201) return reject(xhr);
const data = JSON.parse(xhr.responseText);
console.log("Got answer: ", data);
return data.code ? reject(xhr) : resolve(data);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 && xhr.status !== 201) 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 && xhr.status !== 201) 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) {
Expand Down
Loading