Skip to content

Commit

Permalink
refactor(assets): set a function to change sdp
Browse files Browse the repository at this point in the history
  • Loading branch information
fastfeee committed Nov 1, 2023
1 parent bf1bcd5 commit 206c546
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 128 deletions.
135 changes: 132 additions & 3 deletions assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
.enumerateDevices()
.then((devices) => {
const videoDevices = devices.filter(
(device) => device.kind === "videoinput" && device.label !== "OBS Virtual Camera",
(device) => device.kind === "videoinput",
);

// Decide whether to request video based on the presence of the camera device
Expand Down Expand Up @@ -351,10 +351,127 @@
});
}
};


//
function onRemoteAnswer(answer) {
const answer_modified = editAnswer(
answer,
document.getElementById("video_codec").value,
document.getElementById("audio_codec").value,
document.getElementById("video_bitrate").value,
document.getElementById("audio_bitrate").value,
document.getElementById("audio_voice").value,
);
return answer_modified;
};
//
const editAnswer = (answer, videoCodec, audioCodec, videoBitrate, audioBitrate, audioVoice) => {
const sections = answer.split("m=");
for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (section.startsWith("video")) {
sections[i] = setVideoBitrate(setCodec(section, videoCodec), videoBitrate);
} else if (section.startsWith("audio")) {
sections[i] = setAudioBitrate(setCodec(section, audioCodec), audioBitrate, audioVoice);
}
}

const answer_modified = sections.join("m=");
return answer_modified;
};
//
const setVideoBitrate = (section, bitrate) => {
let lines = section.split("\r\n");

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("c=")) {
lines = [
...lines.slice(0, i + 1),
"b=TIAS:" + (parseInt(bitrate) * 1024).toString(),
...lines.slice(i + 1),
];
break;
}
}

return lines.join("\r\n");
};
//
const setAudioBitrate = (section, bitrate, voice) => {
let opusPayloadFormat = "";
let lines = section.split("\r\n");

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("a=rtpmap:") && lines[i].toLowerCase().includes("opus/")) {
opusPayloadFormat = lines[i].slice("a=rtpmap:".length).split(" ")[0];
break;
}
}

if (opusPayloadFormat === "") {
return section;
}

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("a=fmtp:" + opusPayloadFormat + " ")) {
if (voice) {
lines[i] =
"a=fmtp:" +
opusPayloadFormat +
" minptime=10;useinbandfec=1;maxaveragebitrate=" +
(parseInt(bitrate) * 1024).toString();
} else {
lines[i] =
"a=fmtp:" +
opusPayloadFormat +
" maxplaybackrate=48000;stereo=1;sprop-stereo=1;maxaveragebitrate" +
(parseInt(bitrate) * 1024).toString();
}
}
}

return lines.join("\r\n");
};
//
const setCodec = (section, codec) => {
const lines = section.split("\r\n");
const lines2 = [];
const payloadFormats = [];

for (const line of lines) {
if (!line.startsWith("a=rtpmap:")) {
lines2.push(line);
} else {
if (line.toLowerCase().includes(codec)) {
payloadFormats.push(line.slice("a=rtpmap:".length).split(" ")[0]);
lines2.push(line);
}
}
}

const lines3 = [];

for (const line of lines2) {
if (line.startsWith("a=fmtp:")) {
if (payloadFormats.includes(line.slice("a=fmtp:".length).split(" ")[0])) {
lines3.push(line);
}
} else if (line.startsWith("a=rtcp-fb:")) {
if (payloadFormats.includes(line.slice("a=rtcp-fb:".length).split(" ")[0])) {
lines3.push(line);
}
} else {
lines3.push(line);
}
}

return lines3.join("\r\n");
};
// onTransmitSVC

const onTransmitSVC = (stream) => {
document.getElementById("video").srcObject = stream;
console.log(stream);
const resource = document.getElementById("resource").value;
//get svc_level
const rid_value = document.getElementById("svc_level").value;
Expand Down Expand Up @@ -382,7 +499,19 @@
const whip = new WHIPClient();
const url = location.origin + "/whip/" + resource;
const token = document.getElementById("token").value;
whip.publish(pc, url, token);
//whip.publish(pc, url, token);
whip.publish(pc, url, token)
.then((answer) => {
const edit_answer = onRemoteAnswer(answer);
return { pc, edit_answer };
})
.then(({pc,edit_answer}) => {
pc.setRemoteDescription({ type: "answer", sdp: edit_answer });
})
.catch(error => {
console.error("Error publishing:", error);
});

};
// startWhip
async function startWhip() {
Expand Down
130 changes: 5 additions & 125 deletions assets/whip.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//import { EventEmitter } from "events";

class WHIPClient {
constructor() {
//Ice properties
Expand All @@ -11,123 +9,7 @@ class WHIPClient {
this.id = "";
}

async publish(pc, url, token) {
// edit answer_sdp
const onRemoteAnswer = (answer_sdp) => {
const answer_modified = editAnswer(
answer_sdp,
document.getElementById("video_codec").value,
document.getElementById("audio_codec").value,
document.getElementById("video_bitrate").value,
document.getElementById("audio_bitrate").value,
document.getElementById("audio_voice").value,
);
return answer_modified;
};

const editAnswer = (answer_sdp, videoCodec, audioCodec, videoBitrate, audioBitrate, audioVoice) => {
const sections = answer_sdp.split("m=");
for (let i = 0; i < sections.length; i++) {
const section = sections[i];
if (section.startsWith("video")) {
sections[i] = setVideoBitrate(setCodec(section, videoCodec), videoBitrate);
} else if (section.startsWith("audio")) {
sections[i] = setAudioBitrate(setCodec(section, audioCodec), audioBitrate, audioVoice);
}
}

const answer_modified = sections.join("m=");
console.log(answer_modified);
return answer_modified;
};

const setVideoBitrate = (section, bitrate) => {
let lines = section.split("\r\n");

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("c=")) {
lines = [
...lines.slice(0, i + 1),
"b=TIAS:" + (parseInt(bitrate) * 1024).toString(),
...lines.slice(i + 1),
];
break;
}
}

return lines.join("\r\n");
};

const setAudioBitrate = (section, bitrate, voice) => {
let opusPayloadFormat = "";
let lines = section.split("\r\n");

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("a=rtpmap:") && lines[i].toLowerCase().includes("opus/")) {
opusPayloadFormat = lines[i].slice("a=rtpmap:".length).split(" ")[0];
break;
}
}

if (opusPayloadFormat === "") {
return section;
}

for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith("a=fmtp:" + opusPayloadFormat + " ")) {
if (voice) {
lines[i] =
"a=fmtp:" +
opusPayloadFormat +
" minptime=10;useinbandfec=1;maxaveragebitrate=" +
(parseInt(bitrate) * 1024).toString();
} else {
lines[i] =
"a=fmtp:" +
opusPayloadFormat +
" maxplaybackrate=48000;stereo=1;sprop-stereo=1;maxaveragebitrate" +
(parseInt(bitrate) * 1024).toString();
}
}
}

return lines.join("\r\n");
};

const setCodec = (section, codec) => {
const lines = section.split("\r\n");
const lines2 = [];
const payloadFormats = [];

for (const line of lines) {
if (!line.startsWith("a=rtpmap:")) {
lines2.push(line);
} else {
if (line.toLowerCase().includes(codec)) {
payloadFormats.push(line.slice("a=rtpmap:".length).split(" ")[0]);
lines2.push(line);
}
}
}

const lines3 = [];

for (const line of lines2) {
if (line.startsWith("a=fmtp:")) {
if (payloadFormats.includes(line.slice("a=fmtp:".length).split(" ")[0])) {
lines3.push(line);
}
} else if (line.startsWith("a=rtcp-fb:")) {
if (payloadFormats.includes(line.slice("a=rtcp-fb:".length).split(" ")[0])) {
lines3.push(line);
}
} else {
lines3.push(line);
}
}

return lines3.join("\r\n");
};
async publish(pc, url, token) {
//If already publishing
if (this.pc) throw new Error("Already publishing");

Expand Down Expand Up @@ -169,7 +51,6 @@ class WHIPClient {
};
//Create SDP offer
const offer = await pc.createOffer();

//Request headers
const headers = {
"Content-Type": "application/sdp",
Expand Down Expand Up @@ -238,7 +119,6 @@ class WHIPClient {
}
}
}

//Get current config
const config = pc.getConfiguration();

Expand Down Expand Up @@ -276,6 +156,8 @@ class WHIPClient {

//Get the SDP answer
const answer = await fetched.text();
//const edit_answer = await onRemoteAnswer(answer);

this.id = fetched.headers.get("E-tag");
//Schedule trickle on next tick
if (!this.iceTrickeTimeout) this.iceTrickeTimeout = setTimeout(() => this.trickle(), 0);
Expand All @@ -295,11 +177,9 @@ class WHIPClient {
this.iceUsername = offer.sdp.match(/a=ice-ufrag:(.*)\r\n/)[1];
this.icePassword = offer.sdp.match(/a=ice-pwd:(.*)\r\n/)[1];
//}

return answer;
//And set remote description
const answer_sdp = onRemoteAnswer(answer);
console.log(answer_sdp);
await pc.setRemoteDescription({ type: "answer", sdp: answer_sdp });
await pc.setRemoteDescription({ type: "answer", sdp: edit_answer });
}

restart() {
Expand Down

0 comments on commit 206c546

Please sign in to comment.