7-1 【基础铺垫,学前有概念】WebRTC录制基本知识

图片.png
图片.png
图片.png
图片.png
图片.png

7-2 【来点实战】录制音视频实战

录制完后开始播放。
图片.png
录制完后也可以单击下载。

  1. <html>
  2. <meta charset="utf-8">
  3. <head>
  4. <title>WebRTC 获取视频和音频</title>
  5. <style>
  6. .none {
  7. -webkit-filter: none;
  8. }
  9. .blur {
  10. -webkit-filter: blur(3px);
  11. }
  12. .grayscale {
  13. -webkit-filter: grayscale(1);
  14. }
  15. .invert {
  16. -webkit-filter: invert(1);
  17. }
  18. .sepia {
  19. -webkit-filter: sepia(1);
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <section>
  25. <div>
  26. <label>audio input device:</label>
  27. <select id="audioSource"></select>
  28. </div>
  29. <div>
  30. <label>audio output device:</label>
  31. <select id="audioOutput"></select>
  32. </div>
  33. <div>
  34. <label>video input device:</label>
  35. <select id="videoSource"></select>
  36. </div>
  37. </section>
  38. <section>
  39. <div>
  40. <label>Filter:</label>
  41. <select id="filter">
  42. <option value="none">None</option>
  43. <option value="blur">blur</option>
  44. <option value="grayscale">Grayscale</option>
  45. <option value="invert">Invert</option>
  46. <option value="sepia">sepia</option>
  47. </select>
  48. </div>
  49. </section>
  50. <section>
  51. <table>
  52. <!-- <audio autoplay controls id="audioplayer"></audio> -->
  53. <tr>
  54. <td><video autoplay playsinline id="player"></video> </td>
  55. <td><video playsinline id="recplayer"></video></td>
  56. <td><div id='constraints' class='output'></div></td>
  57. </tr>
  58. <tr>
  59. <td><button id="record">Start Record</button></td>
  60. <td><button id="recplay" disabled>Play</button></td>
  61. <td><button id="download" disabled>Download</button></td>
  62. </tr>
  63. </table>
  64. </section>
  65. <section>
  66. <div>
  67. <button id="snapshot">Take snapshot</button>
  68. </div>
  69. <div>
  70. <canvas id="picture"></canvas>
  71. </div>
  72. </section>
  73. <script src="http://webrtc.github.io/adapter/adapter-latest.js"></script>
  74. <script src="./js/client.js"></script>
  75. </body>
  76. </html>
  1. 'use strict'
  2. //devices
  3. var audioSource = document.querySelector('select#audioSource');
  4. var audioOutput = document.querySelector('select#audioOutput');
  5. var videoSource = document.querySelector('select#videoSource');
  6. //filter
  7. var filtersSelect = document.querySelector('select#filter');
  8. //picture
  9. var snapshot = document.querySelector('button#snapshot');
  10. var picture = document.querySelector('canvas#picture');
  11. picture.width = 640;
  12. picture.height = 480;
  13. //videoplay
  14. var videoplay = document.querySelector('video#player');
  15. //var audioplay = document.querySelector('audio#audioplayer');
  16. //div
  17. var divConstraints = document.querySelector('div#constraints');
  18. //record
  19. var recvideo = document.querySelector('video#recplayer');
  20. var btnRecord = document.querySelector('button#record');
  21. var btnPlay = document.querySelector('button#recplay');
  22. var btnDownload = document.querySelector('button#download');
  23. var buffer;
  24. var mediaRecorder;
  25. function gotDevices(deviceInfos){
  26. deviceInfos.forEach(function(deviceinfo){
  27. var option = document.createElement('option');
  28. option.text = deviceinfo.label;
  29. option.value = deviceinfo.deviceId;
  30. if(deviceinfo.kind === 'audioinput'){
  31. audioSource.appendChild(option);
  32. }else if(deviceinfo.kind === 'audiooutput'){
  33. audioOutput.appendChild(option);
  34. }else if(deviceinfo.kind === 'videoinput'){
  35. videoSource.appendChild(option);
  36. }
  37. })
  38. }
  39. function gotMediaStream(stream){
  40. var videoTrack = stream.getVideoTracks()[0];
  41. var videoConstraints = videoTrack.getSettings();
  42. divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);
  43. window.stream = stream;
  44. videoplay.srcObject = stream;
  45. //audioplay.srcObject = stream;
  46. return navigator.mediaDevices.enumerateDevices();
  47. }
  48. function handleError(err){
  49. console.log('getUserMedia error:', err);
  50. }
  51. //匹配视频设备切换
  52. function start() {
  53. if(!navigator.mediaDevices ||
  54. !navigator.mediaDevices.getUserMedia){
  55. console.log('getUserMedia is not supported!');
  56. }else{
  57. var deviceId = videoSource.value;
  58. var constraints = {
  59. video : {
  60. width: 640,
  61. height: 480,
  62. frameRate: 15,
  63. facingMode: 'environment' ,
  64. deviceId : deviceId ? {exact:deviceId} : undefined
  65. },
  66. audio : false
  67. //{
  68. //noiseSuppression: true,
  69. //echoCancellation: true
  70. //}
  71. }
  72. navigator.mediaDevices.getUserMedia(constraints)
  73. .then(gotMediaStream)
  74. .then(gotDevices)
  75. .catch(handleError);
  76. }
  77. }
  78. start();
  79. videoSource.onchange = start;
  80. filtersSelect.onchange = function(){
  81. videoplay.className = filtersSelect.value;
  82. }
  83. snapshot.onclick = function() {
  84. picture.className = filtersSelect.value; //如果先前使用了滤镜,则在截图后,也会使用滤镜
  85. picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
  86. }
  87. function handleDataAvailable(e){
  88. if(e && e.data && e.data.size > 0){
  89. buffer.push(e.data);
  90. }
  91. }
  92. function startRecord(){
  93. buffer = [];
  94. var options = {
  95. mimeType: 'video/webm;codecs=vp8'
  96. }
  97. if(!MediaRecorder.isTypeSupported(options.mimeType)){
  98. console.error(`${options.mimeType} is not supported!`);
  99. return;
  100. }
  101. try{
  102. mediaRecorder = new MediaRecorder(window.stream, options);
  103. }catch(e){
  104. console.error('Failed to create MediaRecorder:', e);
  105. return;
  106. }
  107. mediaRecorder.ondataavailable = handleDataAvailable;
  108. mediaRecorder.start(10);
  109. }
  110. function stopRecord(){
  111. mediaRecorder.stop();
  112. }
  113. btnRecord.onclick = ()=>{
  114. if(btnRecord.textContent === 'Start Record'){
  115. startRecord();
  116. btnRecord.textContent = 'Stop Record';
  117. btnPlay.disabled = true;
  118. btnDownload.disabled = true;
  119. }else{
  120. stopRecord();
  121. btnRecord.textContent = 'Start Record';
  122. btnPlay.disabled = false;
  123. btnDownload.disabled = false;
  124. }
  125. }
  126. btnPlay.onclick = ()=> {
  127. var blob = new Blob(buffer, {type: 'video/webm'});
  128. recvideo.src = window.URL.createObjectURL(blob);
  129. recvideo.srcObject = null;
  130. recvideo.controls = true; //控制标签
  131. recvideo.play();
  132. }
  133. btnDownload.onclick = ()=> {
  134. var blob = new Blob(buffer, {type: 'video/webm'});
  135. var url = window.URL.createObjectURL(blob);
  136. var a = document.createElement('a');
  137. a.href = url;
  138. a.style.display = 'none';
  139. a.download = 'aaa.webm';
  140. a.click();
  141. }

7-3 【来点实战】WebRTC采集屏幕数据

图片.png
打开谷歌浏览器,输入 chrome://flags 查看支持的选项
打开下面链接,启动某个功能。
chrome://flags/#enable-experimental-web-platform-features
图片.png
代码实现,主要将上一节的
getUserMedia修改为getDisplayMedia。
图片.png
图片.png代码实现

  1. <html>
  2. <meta charset="utf-8">
  3. <head>
  4. <title>WebRTC 获取视频和音频</title>
  5. <style>
  6. .none {
  7. -webkit-filter: none;
  8. }
  9. .blur {
  10. -webkit-filter: blur(3px);
  11. }
  12. .grayscale {
  13. -webkit-filter: grayscale(1);
  14. }
  15. .invert {
  16. -webkit-filter: invert(1);
  17. }
  18. .sepia {
  19. -webkit-filter: sepia(1);
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <section>
  25. <div>
  26. <label>audio input device:</label>
  27. <select id="audioSource"></select>
  28. </div>
  29. <div>
  30. <label>audio output device:</label>
  31. <select id="audioOutput"></select>
  32. </div>
  33. <div>
  34. <label>video input device:</label>
  35. <select id="videoSource"></select>
  36. </div>
  37. </section>
  38. <section>
  39. <div>
  40. <label>Filter:</label>
  41. <select id="filter">
  42. <option value="none">None</option>
  43. <option value="blur">blur</option>
  44. <option value="grayscale">Grayscale</option>
  45. <option value="invert">Invert</option>
  46. <option value="sepia">sepia</option>
  47. </select>
  48. </div>
  49. </section>
  50. <section>
  51. <table>
  52. <!-- <audio autoplay controls id="audioplayer"></audio> -->
  53. <tr>
  54. <td><video autoplay playsinline id="player"></video> </td>
  55. <td><video playsinline id="recplayer"></video></td>
  56. <td><div id='constraints' class='output'></div></td>
  57. </tr>
  58. <tr>
  59. <td><button id="record">Start Record</button></td>
  60. <td><button id="recplay" disabled>Play</button></td>
  61. <td><button id="download" disabled>Download</button></td>
  62. </tr>
  63. </table>
  64. </section>
  65. <section>
  66. <div>
  67. <button id="snapshot">Take snapshot</button>
  68. </div>
  69. <div>
  70. <canvas id="picture"></canvas>
  71. </div>
  72. </section>
  73. <script src="http://webrtc.github.io/adapter/adapter-latest.js"></script>
  74. <script src="./js/client.js"></script>
  75. </body>
  76. </html>
  1. 'use strict'
  2. //devices
  3. var audioSource = document.querySelector('select#audioSource');
  4. var audioOutput = document.querySelector('select#audioOutput');
  5. var videoSource = document.querySelector('select#videoSource');
  6. //filter
  7. var filtersSelect = document.querySelector('select#filter');
  8. //picture
  9. var snapshot = document.querySelector('button#snapshot');
  10. var picture = document.querySelector('canvas#picture');
  11. picture.width = 640;
  12. picture.height = 480;
  13. //videoplay
  14. var videoplay = document.querySelector('video#player');
  15. //var audioplay = document.querySelector('audio#audioplayer');
  16. //div
  17. var divConstraints = document.querySelector('div#constraints');
  18. //record
  19. var recvideo = document.querySelector('video#recplayer');
  20. var btnRecord = document.querySelector('button#record');
  21. var btnPlay = document.querySelector('button#recplay');
  22. var btnDownload = document.querySelector('button#download');
  23. var buffer;
  24. var mediaRecorder;
  25. function gotDevices(deviceInfos){
  26. deviceInfos.forEach(function(deviceinfo){
  27. var option = document.createElement('option');
  28. option.text = deviceinfo.label;
  29. option.value = deviceinfo.deviceId;
  30. if(deviceinfo.kind === 'audioinput'){
  31. audioSource.appendChild(option);
  32. }else if(deviceinfo.kind === 'audiooutput'){
  33. audioOutput.appendChild(option);
  34. }else if(deviceinfo.kind === 'videoinput'){
  35. videoSource.appendChild(option);
  36. }
  37. })
  38. }
  39. function gotMediaStream(stream){
  40. var videoTrack = stream.getVideoTracks()[0];
  41. var videoConstraints = videoTrack.getSettings();
  42. divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);
  43. window.stream = stream;
  44. videoplay.srcObject = stream;
  45. //audioplay.srcObject = stream;
  46. return navigator.mediaDevices.enumerateDevices();
  47. }
  48. function handleError(err){
  49. console.log('getDisplayMedia error:', err);
  50. }
  51. //匹配视频设备切换
  52. function start() {
  53. if(!navigator.mediaDevices ||
  54. !navigator.mediaDevices.getDisplayMedia){
  55. console.log('getDisplayMedia is not supported!');
  56. }else{
  57. var deviceId = videoSource.value;
  58. var constraints = {
  59. // video : {
  60. // width: 640,
  61. // height: 480,
  62. // frameRate: 15,
  63. // facingMode: 'environment' ,
  64. // deviceId : deviceId ? {exact:deviceId} : undefined
  65. // },
  66. video :true,
  67. audio : false
  68. //{
  69. //noiseSuppression: true,
  70. //echoCancellation: true
  71. //}
  72. }
  73. navigator.mediaDevices.getDisplayMedia(constraints)
  74. .then(gotMediaStream)
  75. .then(gotDevices)
  76. .catch(handleError);
  77. }
  78. }
  79. start();
  80. videoSource.onchange = start;
  81. filtersSelect.onchange = function(){
  82. videoplay.className = filtersSelect.value;
  83. }
  84. snapshot.onclick = function() {
  85. picture.className = filtersSelect.value; //如果先前使用了滤镜,则在截图后,也会使用滤镜
  86. picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
  87. }
  88. function handleDataAvailable(e){
  89. if(e && e.data && e.data.size > 0){
  90. buffer.push(e.data);
  91. }
  92. }
  93. function startRecord(){
  94. buffer = [];
  95. var options = {
  96. mimeType: 'video/webm;codecs=vp8'
  97. }
  98. if(!MediaRecorder.isTypeSupported(options.mimeType)){
  99. console.error(`${options.mimeType} is not supported!`);
  100. return;
  101. }
  102. try{
  103. mediaRecorder = new MediaRecorder(window.stream, options);
  104. }catch(e){
  105. console.error('Failed to create MediaRecorder:', e);
  106. return;
  107. }
  108. mediaRecorder.ondataavailable = handleDataAvailable;
  109. mediaRecorder.start(10);
  110. }
  111. function stopRecord(){
  112. mediaRecorder.stop();
  113. }
  114. btnRecord.onclick = ()=>{
  115. if(btnRecord.textContent === 'Start Record'){
  116. startRecord();
  117. btnRecord.textContent = 'Stop Record';
  118. btnPlay.disabled = true;
  119. btnDownload.disabled = true;
  120. }else{
  121. stopRecord();
  122. btnRecord.textContent = 'Start Record';
  123. btnPlay.disabled = false;
  124. btnDownload.disabled = false;
  125. }
  126. }
  127. btnPlay.onclick = ()=> {
  128. var blob = new Blob(buffer, {type: 'video/webm'});
  129. recvideo.src = window.URL.createObjectURL(blob);
  130. recvideo.srcObject = null;
  131. recvideo.controls = true; //控制标签
  132. recvideo.play();
  133. }
  134. btnDownload.onclick = ()=> {
  135. var blob = new Blob(buffer, {type: 'video/webm'});
  136. var url = window.URL.createObjectURL(blob);
  137. var a = document.createElement('a');
  138. a.href = url;
  139. a.style.display = 'none';
  140. a.download = 'aaa.webm';
  141. a.click();
  142. }

代码手写.zip06_07chapter.zip