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