publish.html 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>测试WebRTC推流</title>
  8. </head>
  9. <body>
  10. <video id="video" width="640" height="480" autoplay muted>
  11. </video>
  12. <!-- <button id="sw" onclick="action()" type="button" style="width:100px;height:30px;display: block;">unpublish</button> -->
  13. <div id="camera"></div>
  14. <pre>
  15. <code id="remoteSdp">
  16. </code>
  17. </pre>
  18. </body>
  19. <script>
  20. let action = () => { console.log('action not set'); };
  21. const screenshare = location.pathname.endsWith("screenshare");
  22. (async () => {
  23. const searchParams = new URLSearchParams(location.search);
  24. const $camera = document.getElementById('camera');
  25. navigator.mediaDevices.enumerateDevices().then((devices) => {
  26. devices.forEach((device) => {
  27. console.log(device.kind + ": " + device.label + " id = " + device.deviceId);
  28. if (device.kind == 'videoinput' && !screenshare) {
  29. const a = document.createElement('a');
  30. a.href = location.pathname + '?videoinput=' + device.deviceId;
  31. a.innerHTML = device.label;
  32. $camera.appendChild(a);
  33. $camera.appendChild(document.createElement('br'));
  34. }
  35. });
  36. });
  37. const mediaStream = await (screenshare ? navigator.mediaDevices.getDisplayMedia() : navigator.mediaDevices.getUserMedia({
  38. video: searchParams.get('videoinput') ? {
  39. deviceId: searchParams.get('videoinput'),
  40. } : true,
  41. audio: true,
  42. }));
  43. searchParams.delete('videoinput');
  44. document.getElementById('video').srcObject = mediaStream;
  45. const pc = new RTCPeerConnection();
  46. pc.oniceconnectionstatechange = () => {
  47. console.log('oniceconnectionstatechange', pc.iceConnectionState);
  48. };
  49. pc.onicecandidate = (e) => {
  50. console.log('onicecandidate', e.candidate);
  51. };
  52. const streamPath = searchParams.get('streamPath') || 'live/webrtc';
  53. searchParams.delete('streamPath');
  54. mediaStream.id = streamPath;
  55. mediaStream.getTracks().forEach((t) => {
  56. pc.addTrack(t, mediaStream);
  57. });
  58. // const videoTransceiver = pc.addTransceiver(mediaStream.getVideoTracks()[0], { direction: 'sendonly' });
  59. // const audioTransceiver = pc.addTransceiver(mediaStream.getAudioTracks()[0], { direction: 'sendonly' });
  60. // const dc = pc.createDataChannel('sdp');
  61. const offer = await pc.createOffer();
  62. await pc.setLocalDescription(offer);
  63. const result = await fetch(
  64. `/webrtc/push/${streamPath}${location.search ? `?${searchParams.toString()}` : ''}`,
  65. {
  66. method: 'POST',
  67. mode: 'cors',
  68. cache: 'no-cache',
  69. credentials: 'include',
  70. redirect: 'follow',
  71. referrerPolicy: 'no-referrer',
  72. headers: { 'Content-Type': 'application/sdp' },
  73. body: offer.sdp,
  74. },
  75. );
  76. const remoteSdp = await result.text();
  77. document.getElementById('remoteSdp').innerText = remoteSdp;
  78. await pc.setRemoteDescription(
  79. new RTCSessionDescription({ type: 'answer', sdp: remoteSdp }),
  80. );
  81. // dc.onmessage = async (e) => {
  82. // await pc.setRemoteDescription(
  83. // new RTCSessionDescription({ type: 'answer', sdp: e.data }),
  84. // );
  85. // };
  86. // const publish = async () => {
  87. // videoTransceiver.direction = 'sendonly';
  88. // audioTransceiver.direction = 'sendonly';
  89. // const offer = await pc.createOffer();
  90. // await pc.setLocalDescription(offer);
  91. // dc.send('1' + offer.sdp);
  92. // action = unpublish;
  93. // document.getElementById('sw').innerText = 'unpublish';
  94. // };
  95. // const unpublish = async () => {
  96. // videoTransceiver.direction = 'inactive';
  97. // audioTransceiver.direction = 'inactive';
  98. // const offer = await pc.createOffer();
  99. // await pc.setLocalDescription(offer);
  100. // dc.send('0' + offer.sdp);
  101. // action = publish;
  102. // document.getElementById('sw').innerText = 'publish';
  103. // };
  104. // action = unpublish;
  105. })()
  106. </script>
  107. </html>