videoSource.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. const { RTCVideoSource } = require('wrtc').nonstandard;
  2. const ffmpeg = require('fluent-ffmpeg')
  3. class VideoSourceService extends RTCVideoSource {
  4. constructor() {
  5. super() //videosource int
  6. this.command = null // 存储视频源
  7. this.cache = Buffer.alloc(0)
  8. }
  9. // 创建通道
  10. createTrack() {
  11. const track = super.createTrack()
  12. return track
  13. }
  14. // 获取视频源
  15. async start() {
  16. if (this.command !== null) this.stop()
  17. const width = 400, height = 300
  18. // libx264编码后花屏
  19. this.command = ffmpeg('/dev/video0')
  20. .size(`${width}x${height}`)
  21. .outputOptions(['-pix_fmt yuv420p'])
  22. .format("rawvideo")
  23. .on('start', () => {
  24. console.log('Video start !');
  25. })
  26. .on('error', (err) => {
  27. console.log('Video processing An error occurred: ' + err.message);
  28. // 退出进程
  29. process.exit(1)
  30. })
  31. this.ffstream = this.command.pipe();
  32. this.ffstream.on('data', (buffer) => {
  33. this.cache = Buffer.concat([this.cache, buffer])
  34. });
  35. // 整理buffer
  36. const frameSize = width * height * 1.5;
  37. const processData = () => {
  38. while (this.cache.length > frameSize) {
  39. const buffer = this.cache.slice(0, frameSize)
  40. this.cache = this.cache.slice(frameSize)
  41. this.onFrame({
  42. width,
  43. height,
  44. data: new Uint8ClampedArray(buffer)
  45. })
  46. }
  47. if (this.command !== null) {
  48. setTimeout(() => processData())
  49. }
  50. }
  51. processData()
  52. }
  53. // 停止获取
  54. stop() {
  55. console.log("Video source stop");
  56. if (this.command != null) {
  57. this.command.kill("SIGHUP")
  58. this.command = null
  59. }
  60. }
  61. }
  62. module.exports = VideoSourceService