camtest.html 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Webcam Stream with Screenshot</title>
  7. <style>
  8. video {
  9. width: 40%;
  10. margin: 10px;
  11. }
  12. #controls {
  13. margin-top: 10px;
  14. }
  15. #logs {
  16. width: 80%;
  17. height: 150px;
  18. margin-top: 10px;
  19. }
  20. </style>
  21. </head>
  22. <body>
  23. <h1>Webkit WebRTC Demo!</h1>
  24. <video id="localVideo" playsinline autoplay muted></video>
  25. <div id="controls">
  26. <button id="callButton" onclick="call()">Start Call</button>
  27. <button id="hangupButton" disabled onclick="hangup()">Hang Up</button>
  28. <button id="screenshotButton" onclick="takeScreenshot()">Take Screenshot</button>
  29. <button id="switchCamButton" onclick="switchCamera()">Switch Camera</button>
  30. </div>
  31. <div id="bitrateGraph"></div>
  32. <canvas id="bitrateCanvas" width="400" height="200"></canvas>
  33. <div id="packetGraph"></div>
  34. <canvas id="packetCanvas" width="400" height="200"></canvas>
  35. <!-- Textarea for logs -->
  36. <textarea id="logs" readonly></textarea>
  37. <script>
  38. let localStream;
  39. let pc1;
  40. let pc2;
  41. let currentVideoDeviceIndex = 0;
  42. let videoDevices = [];
  43. const offerOptions = {
  44. offerToReceiveAudio: 1,
  45. offerToReceiveVideo: 1
  46. };
  47. const callButton = document.getElementById('callButton');
  48. const hangupButton = document.getElementById('hangupButton');
  49. const screenshotButton = document.getElementById('screenshotButton');
  50. const localVideo = document.getElementById('localVideo');
  51. const logsTextarea = document.getElementById('logs');
  52. function log(message) {
  53. console.log(message);
  54. logsTextarea.value += message + '\n';
  55. }
  56. function gotStream(stream) {
  57. hangupButton.disabled = false;
  58. log('Received local stream');
  59. localStream = stream;
  60. localVideo.srcObject = stream;
  61. localStream.getTracks().forEach(track => pc1.addTrack(track, localStream));
  62. log('Adding Local Stream to peer connection');
  63. pc1.createOffer(offerOptions).then(gotDescription1, onCreateSessionDescriptionError);
  64. }
  65. function call() {
  66. callButton.disabled = true;
  67. log('Starting call');
  68. pc1 = new RTCPeerConnection(null);
  69. log('Created local peer connection object pc1');
  70. pc1.onicecandidate = e => onIceCandidate(e, pc1);
  71. pc2 = new RTCPeerConnection(null);
  72. log('Created remote peer connection object pc2');
  73. pc2.onicecandidate = e => onIceCandidate(e, pc2);
  74. pc2.ontrack = gotRemoteStream;
  75. log('Requesting live local stream');
  76. navigator.mediaDevices.enumerateDevices().then(gotDevices).then(getUserMedia).catch(e => alert('getUserMedia() error: ' + e.name));
  77. }
  78. function gotDevices(deviceInfos) {
  79. videoDevices = deviceInfos.filter(deviceInfo => deviceInfo.kind === 'videoinput');
  80. }
  81. function getUserMedia() {
  82. const videoSource = videoDevices[currentVideoDeviceIndex].deviceId;
  83. const constraints = {
  84. video: { deviceId: videoSource ? { exact: videoSource } : undefined }
  85. };
  86. navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(e => alert('getUserMedia() error: ' + e.name));
  87. }
  88. function switchCamera() {
  89. if (videoDevices.length > 1) {
  90. currentVideoDeviceIndex = (currentVideoDeviceIndex + 1) % videoDevices.length;
  91. localStream.getTracks().forEach(track => track.stop());
  92. getUserMedia();
  93. } else {
  94. log('No other camera found to switch.');
  95. }
  96. }
  97. function gotDescription1(desc) {
  98. log(`Offer from pc1\n${desc.sdp}`);
  99. pc1.setLocalDescription(desc).then(() => {
  100. pc2.setRemoteDescription(desc).then(() => {
  101. pc2.createAnswer().then(gotDescription2, onCreateSessionDescriptionError);
  102. }, onSetSessionDescriptionError);
  103. }, onSetSessionDescriptionError);
  104. }
  105. function gotDescription2(desc) {
  106. log(`Answer from pc2\n${desc.sdp}`);
  107. pc2.setLocalDescription(desc).then(() => {
  108. pc1.setRemoteDescription(desc).then(() => {}, onSetSessionDescriptionError);
  109. }, onSetSessionDescriptionError);
  110. }
  111. function gotRemoteStream(event) {
  112. if (remoteVideo.srcObject !== event.streams[0]) {
  113. remoteVideo.srcObject = event.streams[0];
  114. log('Received remote stream');
  115. }
  116. }
  117. function onIceCandidate(event, pc) {
  118. const otherPc = (pc === pc1) ? pc2 : pc1;
  119. otherPc.addIceCandidate(event.candidate).then(() => {
  120. log('AddIceCandidate success.');
  121. }, err => {
  122. log(`Failed to add Ice Candidate: ${err.toString()}`);
  123. });
  124. }
  125. function onSetSessionDescriptionError(error) {
  126. log(`Failed to set session description: ${error.toString()}`);
  127. }
  128. function onCreateSessionDescriptionError(error) {
  129. log(`Failed to create session description: ${error.toString()}`);
  130. }
  131. function hangup() {
  132. pc1.close();
  133. pc2.close();
  134. pc1 = null;
  135. pc2 = null;
  136. hangupButton.disabled = true;
  137. callButton.disabled = false;
  138. log('Ending call');
  139. }
  140. function takeScreenshot() {
  141. const canvas = document.createElement('canvas');
  142. canvas.width = localVideo.videoWidth;
  143. canvas.height = localVideo.videoHeight;
  144. canvas.getContext('2d').drawImage(localVideo, 0, 0, canvas.width, canvas.height);
  145. canvas.toBlob(blob => {
  146. const formData = new FormData();
  147. formData.append('file', blob, 'screenshot.png');
  148. const netloc = document.domain; // Get the hostname and port of the current site
  149. fetch(`https://${netloc}/`, { // Adjust the URL here if needed
  150. method: 'POST',
  151. body: formData
  152. })
  153. .then(response => response.json())
  154. .then(data => {
  155. log(`Screenshot uploaded successfully: ${data.message}`);
  156. })
  157. .catch(error => {
  158. log(`Error uploading screenshot: ${error.toString()}`);
  159. });
  160. }, 'image/png');
  161. }
  162. </script>
  163. </body>
  164. </html>