audioSource.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. const { RTCAudioSource } = require('wrtc').nonstandard;
  2. const ffmpeg = require('fluent-ffmpeg')
  3. class AudioSourceService extends RTCAudioSource {
  4. constructor() {
  5. super();
  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. start() {
  16. if (this.command !== null) this.stop()
  17. this.command = ffmpeg("plughw:1,0")
  18. .inputFormat("alsa")
  19. .audioChannels(1)
  20. .audioFrequency(48000)
  21. .audioCodec("pcm_s16le")
  22. .outputFormat("s16le")
  23. .on("start", () => {
  24. console.log("Audio start !");
  25. })
  26. .on("error", function (err) {
  27. console.log('Audio 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. // console.log("Audio buffer length", buffer.length);
  34. this.cache = Buffer.concat([this.cache, buffer]);
  35. });
  36. const processData = () => {
  37. while (this.cache.length > 960) {
  38. const buffer = this.cache.slice(0, 960);
  39. this.cache = this.cache.slice(960);
  40. const samples = new Int16Array(new Uint8Array(buffer).buffer);
  41. this.onData({
  42. bitsPerSample: 16,
  43. sampleRate: 48000,
  44. channelCount: 1,
  45. numberOfFrames: samples.length,
  46. type: "data",
  47. samples,
  48. });
  49. }
  50. if (this.command !== null) {
  51. setTimeout(() => processData(), 10);
  52. }
  53. };
  54. processData();
  55. }
  56. // 停止获取
  57. stop() {
  58. console.log("audio source stop");
  59. if (this.command != null) {
  60. this.command.kill("SIGHUP")
  61. this.command = null
  62. }
  63. }
  64. }
  65. module.exports = AudioSourceService