main.html 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>libdatachannel media example</title>
  6. </head>
  7. <body>
  8. <div style="display:inline-block; width:40%;">
  9. <h1>SENDER</h1>
  10. <p id="send-help">Please enter the offer provided to you by the application: </p>
  11. <textarea style="width:100%;" id=send-text rows="50"></textarea>
  12. <button id=send-btn>Submit</button>
  13. </div>
  14. <div style="display:inline-block; width:40%;">
  15. <h1>RECEIVER</h1>
  16. <p id="recv-help">Please enter the offer provided to you by the application: </p>
  17. <textarea id=recv-text style="width:100%;" rows="50"></textarea>
  18. <button id=recv-btn>Submit</button>
  19. </div>
  20. <div id="videos">
  21. </div>
  22. <script>
  23. document.querySelector('#send-btn').addEventListener('click', async () => {
  24. let offer = JSON.parse(document.querySelector('#send-text').value);
  25. rtc = new RTCPeerConnection({
  26. // Recommended for libdatachannel
  27. bundlePolicy: "max-bundle",
  28. });
  29. rtc.onicegatheringstatechange = (state) => {
  30. if (rtc.iceGatheringState === 'complete') {
  31. // We only want to provide an answer once all of our candidates have been added to the SDP.
  32. let answer = rtc.localDescription;
  33. document.querySelector('#send-text').value = JSON.stringify({"type": answer.type, sdp: answer.sdp});
  34. document.querySelector('#send-help').value = 'Please paste the answer in the application.';
  35. alert('Please paste the answer in the application.');
  36. }
  37. }
  38. await rtc.setRemoteDescription(offer);
  39. let media = await navigator.mediaDevices.getUserMedia({
  40. video: {
  41. width: 1280,
  42. height: 720
  43. }
  44. });
  45. media.getTracks().forEach(track => rtc.addTrack(track, media));
  46. let answer = await rtc.createAnswer();
  47. await rtc.setLocalDescription(answer);
  48. });
  49. document.querySelector('#recv-btn').addEventListener('click', async () => {
  50. let offer = JSON.parse(document.querySelector('#recv-text').value);
  51. rtc = new RTCPeerConnection({
  52. // Recommended for libdatachannel
  53. bundlePolicy: "max-bundle",
  54. });
  55. rtc.onicegatheringstatechange = (state) => {
  56. if (rtc.iceGatheringState === 'complete') {
  57. // We only want to provide an answer once all of our candidates have been added to the SDP.
  58. let answer = rtc.localDescription;
  59. document.querySelector('#recv-text').value = JSON.stringify({"type": answer.type, sdp: answer.sdp});
  60. document.querySelector('#recv-help').value = 'Please paste the answer in the application.';
  61. alert('Please paste the answer in the application.');
  62. }
  63. }
  64. let trackCount = 0;
  65. rtc.ontrack = (ev) => {
  66. let thisID = trackCount++;
  67. document.querySelector("#videos").innerHTML += "<video width=100% height=100% id='video-" + thisID + "'></video>";
  68. let tracks = [];
  69. rtc.getReceivers().forEach(recv => tracks.push(recv.track));
  70. document.querySelector("#video-" + thisID).srcObject = new MediaStream(tracks);
  71. document.querySelector("#video-" + thisID).play();
  72. };
  73. await rtc.setRemoteDescription(offer);
  74. let answer = await rtc.createAnswer();
  75. await rtc.setLocalDescription(answer);
  76. });
  77. </script>
  78. </body>
  79. </html>