本地USB摄像头在使用中时,不支持另一个程序的并发访问,也就是所USB摄像头只能令第一个连接的程序“独享”。
在开发一个软件时,希望实现预览USB摄像头的同时,实现摄像头的推流。
推流要用的ffmpeg,经过资料查找,ffmpeg支持通过管道传输给ffplay实现本地预览,代码如下:
ffmpeg -f v4l2 -video_size 640x480 -i /dev/video0 -f alsa -i hw:0 -c:v libx264 -preset ultrafast -tune zerolatency -b:v 1000k -minrate 500k -maxrate 2000k -bufsize 2000k -c:a aac -strict experimental -f flv rtmp://server/live/stream | ffplay -
用这个方法弹出的界面不美观,而且对系统资源占用非常高,不建议使用。
经过查询ffmpeg源码,发现有个image2pipe参数,可以完美实现这个需求,具体实现步骤如下:
- 项目中安装AForge用于对摄像头操作
- 设计界面如下
- 窗体载入
// 获取摄像头设备 //获取内置、外接摄像头,非网络摄像头 videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); if (videoDevices.Count != 0) {foreach (FilterInfo device in videoDevices){cbo_camera.Items.Add(device.Name);} } else {cbo_camera.Items.Add("没有找到摄像头"); }cbo_camera.SelectedIndex = 0;
- 选择摄像头
private void cbo_camera_SelectedIndexChanged(object sender, EventArgs e) {if (videoDevices.Count != 0){//获取每个摄像头支持的分辨率videoDevice = new VideoCaptureDevice(videoDevices[cbo_camera.SelectedIndex].MonikerString);GetDeviceResolution(videoDevice);} }
- 获取分辨率
/// <summary> /// 获取每个摄像头支持的分辨率 /// </summary> /// <param name="videoCaptureDevice"></param> private void GetDeviceResolution(VideoCaptureDevice videoCaptureDevice) {cbo_rate.Items.Clear();videoCapabilities = videoCaptureDevice.VideoCapabilities;foreach (VideoCapabilities capabilty in videoCapabilities){cbo_rate.Items.Add($"{capabilty.FrameSize.Width} x {capabilty.FrameSize.Height}");}cbo_rate.SelectedIndex = 0; }
- 摄像头有新帧进入的处理
currentFrame = image; pictureBox1.Image = currentFrame; PushToRtmpServer(currentFrame); Console.WriteLine("NewFrame");
- 为AForge控件添加事件
- PushToRtmpServer代码
private void PushToRtmpServer(Bitmap frame)
{// 将摄像头视频推流到 RTMP 服务器if (ffmpegProcess == null || ffmpegProcess.HasExited){var outputSettings = $"rtmp://192.168.0.66/live/livestream?KeyCode=123";var ffmpegArgs = $"-y -f image2pipe -pix_fmt bgr24 -s {frame.Width}x{frame.Height}" +$" -r 25 -i - -c:v libx264 -preset fast -tune zerolatency -f flv {outputSettings}";var processStartInfo = new ProcessStartInfo("ffmpeg.exe"){RedirectStandardInput = true,UseShellExecute = false,CreateNoWindow = true,Arguments = ffmpegArgs,WindowStyle = ProcessWindowStyle.Hidden};ffmpegProcess = Process.Start(processStartInfo);}using (var ms = new MemoryStream()){this.Invoke((EventHandler)delegate {frame.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);ms.Seek(0, SeekOrigin.Begin);ffmpegProcess.StandardInput.BaseStream.Write(ms.ToArray(), 0, ms.ToArray().Length);});}
}
运行结果:
代码下载: https://download.csdn.net/download/dgnankai/87767380