webrtc浏览器端直播推流示例代码
代码语言:html
所属分类:多媒体
代码描述:webrtc浏览器端直播推流示例代码,直播服务器可以安装mediamtx,地址https://github.com/bluenviron/mediamtx
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
body {
display: flex;
flex-direction: column;
}
#video {
height: 100%;
background: black;
flex-grow: 1;
min-height: 0;
}
#controls {
height: 200px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
#device {
flex-direction: column;
}
#device > div {
margin: 10px 0;
display: flex;
gap: 20px;
justify-content: center;
}
select {
width: 200px;
}
</style>
</head>
<body>
<video id="video" muted controls autoplay playsinline></video>
<div id="controls">
<div id="initializing" style="display: block;">
initializing
</div>
<div id="device" style="display: none;">
<div id="device_line">
video device:
<select id="video_device">
<option value="none">none</option>
</select>
audio device:
<select id="audio_device">
<option value="none">none</option>
</select>
</div>
<div id="codec_line">
video codec:
<select id="video_codec">
</select>
audio codec:
<select id="audio_codec">
</select>
</div>
<div id="bitrate_line">
video bitrate (kbps):
<input id="video_bitrate" type="text" value="10000" />
audio bitrate (kbps):
<input id="audio_bitrate" type="text" value="32" />
<div>
<input id="audio_voice" type="checkbox" checked>
<label for="audio_voice">optimize for voice</label>
</div>
</div>
<div id="submit_line">
<button id="publish_confirm">publish</button>
</div>
</div>
<div id="transmitting" style="display: none;">
publishing
</div>
<div id="error" style="display: none;">
<span id="error-message"></span>
</div>
</div>
<script>
const INITIALIZING = 0;
const DEVICE = 1;
const TRANSMITTING = 2;
const ERROR = 3;
let state = INITIALIZING;
let errorMessage = '';
const render = () => {
for (const el of ['initializing', 'device', 'transmitting', 'error']) {
document.getElementById(el).style.display = 'none';
}
switch (state) {
case DEVICE:
document.getElementById('device').style.display = 'flex';
break;
case TRANSMITTING:
document.getElementById('transmitting').style.display = 'flex';
break;
case ERROR:
document.getElementById('error').style.display = 'flex';
document.getElementById('error-message').innerHTML = 'error: ' + errorMessage;
break;
}
};
const restartPause = 2000;
const unquoteCredential = (v) => (
JSON.parse(`"${v}"`)
);
const linkToIceServers = (links) => (
(links !== null) ? links.split(', ').map((link) => {
const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i);
const ret = {
urls: [m[1]],
};
if (m[3] !== undefined) {
ret.username = unquoteCredential(m[3]);
ret.credential = unquoteCredential(m[4]);
ret.credentialType = "password";
}
return ret;
}) : []
);
const parseOffer = (offer) => {
const ret = {
iceUfrag: '',
icePwd: '',
medias: [],
};
for (const line of offer.split('\r\n')) {
if (line.startsWith('m=')) {
ret.medias.push(line.slice('m='.length));
} else if (ret.iceUfrag === '' && line.startsWith('a=ice-ufrag:')) {
ret.iceUfrag = line.slice('a=ice-ufrag:'.length);
} else if (ret.icePwd === '' && line.startsWith('a=ice-pwd:')) {
ret.icePwd = line.slice('a=ice-pwd:'.length);
}
}
return ret;
};
const generateSdpFragment = (offerData, candidates) => {
const candidatesByMedia = {};
for (const candidate of candidates) {
const mid = candidate.sdpMLineIndex;
if (candidatesByMedia[mid] === undefined) {
candidatesByMedia[mid] = [];
}
candidatesByMedia[mid].push(candidate);
}
let frag = 'a=ice-ufrag:' + offerData.iceUfrag + '\r\n'
+ 'a=ice-pwd:' + offerData.icePwd + '\r\n';
let mid = 0;
for (const media of offerData.medias) {
if (candidatesByMedia[mid] !== undefined) {
frag += 'm=' + media + '\r\n'
+ 'a=mid:' + mid + '\r\n';
for (const candidate of candidatesByMedia[mid]) {
frag += 'a=' + candidate.candidate + '\r\n';
}
}
mid++;
}
return frag;
};
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 (payloadFormat.........完整代码请登录后点击上方下载按钮下载查看
网友评论0