C#推流RTMP,摄像头、麦克风、桌面、声卡(附源码)

本文介绍了一个C#推流项目的实现原理及代码逻辑,包括摄像头、麦克风、桌面和声卡数据的采集与混音,以及通过Nginx-RTMP服务器进行推流的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   这段时间一直都在研究推流的技术,经过断断续续将近两个月的摸索实践,终于能稳定地推流了。

       这个demo的主要功能就是将采集到的摄像头或桌面的视频、以及麦克风或声卡的音频数据推到Nginx-RTMP服务器上,再由Web浏览器去拉流并播放。

  接下来介绍Demo整个功能的实现原理和代码逻辑,大家可以从文末下载源码后,对照源码再来看下面的介绍就会更清晰些。

一.客户端实现

       客户端的界面效果图如下所示:

  

  客户端的具体功能:可以采集摄像头或者桌面图像,也可以采集麦克风与声卡的声音 并将它们推送到Nginx流服务器上。

  从上面功能就可以看出这里需要有多个采集器来采集相关的数据:摄像头采集器、麦克风采集器、桌面采集器、以及声卡采集器。如果需要将麦克风或声卡的声音混音(比如,主播一边用电脑播放背景音乐一边播讲),则还需要使用混音器。

       在点击启动设备按钮时,我们就需要来启动各自对应的采集器,并开始采集:

 
  1. #region 设置采集器

  2. if (this.radioButton_desktop.Checked)

  3. {

  4. //桌面采集器

  5. //如果需要录制鼠标的操作,第二个参数请设置为true

  6. this.desktopCapturer = CapturerFactory.CreateDesktopCapturer(frameRate, false,new Rectangle(0,0,1920,1080));

  7. this.desktopCapturer.ImageCaptured += this.Form1_ImageCaptured;

  8.  
  9. }

  10. else if (this.radioButton_camera.Checked)

  11. {

  12. //摄像头采集器

  13. this.cameraCapturer = CapturerFactory.CreateCameraCapturer(0, this.defaultVideoSize, frameRate);

  14. this.cameraCapturer.ImageCaptured += new CbGeneric<Bitmap>(this.Form1_ImageCaptured);

  15. }

  16.  
  17. if (this.checkBox_micro.Checked)

  18. {

  19. //麦克风采集器

  20. this.microphoneCapturer = CapturerFactory.CreateMicrophoneCapturer(0);

  21. this.microphoneCapturer.CaptureError += new CbGeneric<Exception>(this.CaptureError);

  22. }

  23.  
  24. if (this.checkBox_soundCard.Checked)

  25. {

  26. //声卡采集器 【目前声卡采集仅支持vista以及以上系统】扬声器 属性 高级设置 16位 48000HZ(DVD音质)

  27. this.soundcardCapturer = CapturerFactory.CreateSoundcardCapturer();

  28. this.soundcardCapturer.CaptureError += this.CaptureError;

  29. if (this.soundcardCapturer.SampleRate != 48000)

  30. {

  31. throw new Exception("声卡采样率必须为48000HZ");

  32. }

  33. audioSampleRate = this.soundcardCapturer.SampleRate;

  34. this.channelCount = this.soundcardCapturer.ChannelCount;

  35. }

  36.  
  37. if (this.checkBox_micro.Checked && this.checkBox_soundCard.Checked)

  38. {

  39. //混音器

  40. this.audioMixter = CapturerFactory.CreateAudioMixter(this.microphoneCapturer, this.soundcardCapturer,

  41. SoundcardMode4Mix.DoubleChannel, true);

  42. this.audioMixter.AudioMixed += audioMixter_AudioMixed;

  43. audioSampleRate = this.audioMixter.SampleRate;

  44. this.channelCount = this.audioMixter.ChannelCount;

  45. }

  46.  
  47. else if (this.checkBox_micro.Checked)

  48. {

  49. this.microphoneCapturer.AudioCaptured += audioMixter_AudioMixed;

  50. }

  51. else if (this.checkBox_soundCard.Checked)

  52. {

  53. this.soundcardCapturer.AudioCaptured += audioMixter_AudioMixed;

  54. }

  55. #endregion

  56.  
  57.  
  58. #region //开始采集

  59. if (this.checkBox_micro.Checked)

  60. {

  61. this.microphoneCapturer.Start();

  62. }

  63. if (this.checkBox_soundCard.Checked)

  64. {

  65. this.soundcardCapturer.Start();

  66. }

  67.  
  68. if (this.radioButton_camera.Checked)

  69. {

  70. this.cameraCapturer.Start();

  71. }

  72. else if (this.radioButton_desktop.Checked)

  73. {

  74. this.desktopCapturer.Start();

  75. }

  76. #endregion

  开始采集后,我们就可以点击开始推流按钮,初始化推流器,将采集的数据推到流服务器上:

 
  1. //TODO 开始录制桌面,依据 声音复选框 来选择使用 声卡 麦克风 还是混合录制, 图像复选框来选择 图像的采集器

  2. try

  3. {

  4. int videoWidth = 0, videoHeight = 0;

  5. if (this.radioButton_desktop.Checked)

  6. {

  7. videoWidth = this.desktopCapturer.VideoSize.Width;

  8. videoHeight = this.desktopCapturer.VideoSize.Height;

  9. }

  10. else {

  11. videoWidth = this.defaultVideoSize.Width;

  12. videoHeight = this.defaultVideoSize.Height;

  13. }

  14.  
  15. this.streamPusher.UpsideDown4RGB24 = true;

  16. this.streamPusher.Initialize("192.168.1.56", 9000, true, this.streamID, videoWidth, videoHeight, NPusher.InputAudioDataType.PCM, NPusher.InputVideoDataType.RGB24,this.channelCount);

  17. this.isPushing = true;

  18. this.button_start.Enabled = false;

  19. this.button_stop.Enabled = true;

  20. this.button3.Enabled = false;

  21. this.ShowStateMsg("推流中...");

  22. }

  23. catch (Exception ee)

  24. {

  25. MessageBox.Show(ee.Message);

  26. }

   上述代码中红色标记部分,即是初始化推流器:由于我们采集到的视频是H264数据,声音是PCM数据,所以,在初始化时,选择InputAudioDataType.PCM和InputVideoDataType.RGB24。

      在采集时我们预定了对应的采集事件,采集到数据后我们就加到推流器中,它会自动将数据推到我们的Nginx服务器上:

 
  1. //采集到的视频或桌面图像

  2. void Form1_ImageCaptured(Bitmap img)

  3. {

  4. if (this.radioButton_camera.Checked)//显示摄像头的图像到窗体

  5. {

  6. Image copy = ESBasic.Helpers.ImageHelper.CopyImageDeeply(img);

  7. this.DisplayVideo(copy);

  8. }

  9. if (this.isPushing)

  10. {

  11. img.RotateFlip(RotateFlipType.Rotate180FlipY);

  12. byte[] data = ESBasic.Helpers.ImageHelper.GetRGB24CoreData(img);

  13. this.streamPusher.PushVideoFrame(data);

  14. }

  15. }

  16.  
  17. //采集到的声卡、麦克风、声卡麦克风的混音数据

  18. void audioMixter_AudioMixed(byte[] audioData)

  19. {

  20. if (this.isPushing)

  21. {

  22. if (this.checkBox_soundCard.Checked && !this.checkBox_micro.Checked)

  23. {

  24. audioData = AudioHelper.ConvertTo16kFrom48k(audioData ,this.channelCount);

  25. }

  26. this.streamPusher.PushAudioFrame(audioData);

  27. }

  28. }

  代码中标记为红色的部分PushVideoFrame和PushAudioFrame方法,即是将采集到的视频帧和音频帧推流到流服务器。

 二.Nginx服务端部署

  这里可以在文末网盘下载服务端来部署到服务器上,其中有3个地方需要根据服务器的配置自行做修改

1. conf目录下nginx.conf 文件中 rtmp 端口 9000、http 端口8000 。

2. html目录下index.html 文件中 设置流服务器的IP     

src: "rtmp://192.168.1.56:9000/hls/"+pqs._parameters.id[0], //将192.168.1.56改成流服务器的IP

3. html目录下mobile.html 文件中 也同样设置流服务器的IP 

 var hls_url = "http://192.168.1.56:8000/hls/" + pqs._parameters.id[0] + ".m3u8"; //将192.168.1.56改成流服务器的IP

三.浏览器访问

  PC的浏览器访问 http://192.168.1.56:8000/?id=aa01,其中aa01为流的ID。效果如下图

  

  手机浏览器访问 http://192.168.1.56:8000/mobile.html?id=aa01,其中aa01为流的ID。效果如下图

  

 四.源码下载

     (1) C#推流RTMP(摄像头、麦克风、桌面、声卡)-源码

     (2)Nginx部署版下载 网盘下载 (提取码: 1234)  

              注:查看Nginx运行状态可访问: http://192.168.1.56:8000/stat 。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值