rtmp_video_capturer.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. ; (function (window) {
  2. // 获取 video 元素的宽度和高度
  3. var rtmp_videoChannelWidth;
  4. var rtmp_videoChannelHeight;
  5. // 创建 ImageCapture 对象
  6. var rtmp_videoChannelCapture;
  7. var rtmp_usVideoElement;
  8. var rtmp_captureCanvas;
  9. /// 初始化 imageCapture 并返回 video 宽高
  10. /// [video_id] 传入需要捕获的 video/Canvas 元素的id
  11. function initRTMPVideoCapture(video_id) {
  12. try {
  13. // 获取video元素
  14. rtmp_usVideoElement = document.getElementById(video_id);
  15. try {
  16. // 获取video流
  17. let stream = rtmp_usVideoElement.captureStream();
  18. let track = stream.getVideoTracks()[0];
  19. // 获取video的宽度和高度
  20. const settings = track.getSettings();
  21. rtmp_videoChannelWidth = settings.width;
  22. rtmp_videoChannelHeight = settings.height;
  23. // 创建ImageCapture对象
  24. rtmp_videoChannelCapture = new ImageCapture(track);
  25. } catch (error) {
  26. rtmp_videoChannelCapture = null;
  27. // 获取video元素的宽度和高度
  28. rtmp_videoChannelWidth = rtmp_usVideoElement.videoWidth;
  29. rtmp_videoChannelHeight = rtmp_usVideoElement.videoHeight;
  30. }
  31. // 初始化canvas
  32. rtmp_captureCanvas = document.createElement("canvas");
  33. rtmp_captureCanvas.width = rtmp_videoChannelWidth;
  34. rtmp_captureCanvas.height = rtmp_videoChannelHeight;
  35. return [rtmp_videoChannelWidth, rtmp_videoChannelHeight];
  36. } catch (error) {
  37. return [0, 0];
  38. }
  39. }
  40. function setRTMPClipSize(width, height) {
  41. rtmp_captureCanvas.width = width;
  42. rtmp_captureCanvas.height = height;
  43. }
  44. /// 捕获视频帧并转换为二进制数组返回
  45. function captureRTMPOneFrame() {
  46. if (rtmp_videoChannelCapture == null) {
  47. const context = rtmp_captureCanvas.getContext("2d");
  48. context.drawImage(
  49. rtmp_usVideoElement,
  50. 0,
  51. 0,
  52. rtmp_videoChannelWidth,
  53. rtmp_videoChannelHeight
  54. );
  55. const dataUrl = rtmp_captureCanvas.toDataURL("image/jpeg");
  56. const binary = atob(dataUrl.split(",")[1]);
  57. const uint8Array = new Uint8Array(binary.length);
  58. for (let i = 0; i < binary.length; i++) {
  59. uint8Array[i] = binary.charCodeAt(i);
  60. }
  61. return Promise.resolve(uint8Array);
  62. } else {
  63. const promise = rtmp_videoChannelCapture.grabFrame().then((imageBitmap) => {
  64. const context = rtmp_captureCanvas.getContext("2d");
  65. context.drawImage(
  66. imageBitmap,
  67. 0,
  68. 0,
  69. rtmp_videoChannelWidth,
  70. rtmp_videoChannelHeight
  71. );
  72. const dataUrl = rtmp_captureCanvas.toDataURL("image/jpeg");
  73. const binary = atob(dataUrl.split(",")[1]);
  74. const uint8Array = new Uint8Array(binary.length);
  75. for (let i = 0; i < binary.length; i++) {
  76. uint8Array[i] = binary.charCodeAt(i);
  77. }
  78. return uint8Array;
  79. });
  80. return promise;
  81. }
  82. }
  83. /// 释放 imageCapture 对象
  84. function disposeRTMPVideoCapture() {
  85. rtmp_videoChannelCapture = null;
  86. rtmp_usVideoElement = null;
  87. rtmp_captureCanvas = null;
  88. console.log("rtmp_videoChannelCapture has been disposed");
  89. }
  90. window.rtmpCapturer = {
  91. init: initRTMPVideoCapture,
  92. setClipSize: setRTMPClipSize,
  93. captureOne: captureRTMPOneFrame,
  94. release: disposeRTMPVideoCapture,
  95. }
  96. })(window);