采集视频(二)

V4L2驱动的移植与应用(二) 二、V4L2的应用    下面简单介绍一下V4L2驱动的应用流程。1、  视频采集的基本流程一般的,视频采集都有如下流程:2、  打开视频设备在V4L2中,视频设备被看做一个文件。使用open函数打开这个设备:// 用非阻塞模式打开摄像头设备int cameraFd;cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);// 如果用阻塞模式打开摄像头设备,上述代码变为://cameraFd = open("/dev/video0", O_RDWR, 0 阅读详情

采集视频(二)


概述

音视频采集是直播架构的第一环,是视频的来源

其实视频的采集有多个应用场景:比如二维码开发

音视频采集包括两部分:

视频采集
音频采集

在iOS开发中,是可以同步采集视频&音频的,使用方式也非常简单

相关的采集API都封装在AVFoundation框架中,导入对应框架,实现功能即可


采集步骤

采集步骤文字描述

PS:如果做过二维码开发,应该对相关步骤非常熟悉(非常类似)
导入框架
相关API主要在AVFoundation框架中,因此需要先导入框架
创建捕捉会话(AVCaptureSession)
该会话用于连接之后的输入源&输出源
输入源:摄像头&话筒
输出源:拿到对应的音频&视频数据的出口
会话:用于将输入源&输出源连接起来
设置视频输入源&输出源
输入源(AVCaptureDeviceInput):从摄像头输入
输出源(AVCaptureVideoDataOutput):可以设置代理,在代理方法中拿到数据
将输入&输出添加到会话中
设置音频输入源&输出源
输入源(AVCaptureDeviceInput):从话筒输入
输出源(AVCaptureAudioDataOutput):可以设置代理,在代理方法中拿到数据
将输入&输出添加到会话中
添加预览图层(可选)
如果希望用户看到采集的画面,可以添加预览图层
该预览图层不是必须的,及时没有添加也可以正常采集数据
开始采集即可
调用会话(AVCaptureSession)的startRunning方法即可开始采集

代码解析

整体代码步骤

整体代码步骤

函数一(设置视频输入输出)

函数一

函数二(设置音频输入输出)

函数二

添加预览图层

添加预览图层

遵守协议,实现代理方法

协议

实现代码

整体步骤代码

    // 1.创建捕捉会话
    let session = AVCaptureSession()

    // 2.设置视频输入输出
    setupVideoSource(session: session)

    // 3.设置音频输入输出
    setupAudioSource(session: session)

    // 4.添加预览图层
    setupPreviewLayer(session: session)

    // 5.开始扫描
    session.startRunning()

函数一(设置视频输入输出)

    // 给会话设置视频源(输入源&输出源)
    fileprivate func setupVideoSource(session : AVCaptureSession) {
        // 1.创建输入
        // 1.1.获取所有的设备(包括前置&后置摄像头)
        guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return }

        // 1.2.取出获取前置摄像头
        let d = devices.filter({ return $0.position == .front }).first

        // 1.3.通过前置摄像头创建输入设备
        guard let videoInput = try? AVCaptureDeviceInput(device: d) else { return }

        // 2.创建输出源
        // 2.1.创建视频输出源
        let videoOutput = AVCaptureVideoDataOutput()

        // 2.2.设置代理,以及代理方法的执行队列(在代理方法中拿到采集到的数据)
        let queue = DispatchQueue.global()
        videoOutput.setSampleBufferDelegate(self, queue: queue)

        // 3.将输入&输出添加到会话中
        // 3.1.添加输入源
        if session.canAddInput(videoInput) {
            session.addInput(videoInput)
        }

        // 3.2.添加输出源
        if session.canAddOutput(videoOutput) {
            session.addOutput(videoOutput)
        }

        // 4.给connect赋值
        videoConnect = videoOutput.connection(withMediaType: AVMediaTypeVideo)
    }

函数二(设置音频输入输出)

    // 给会话设置音频源(输入源&输出源)
    fileprivate func setupAudioSource(session : AVCaptureSession) {
        // 1.创建输入
        guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) else { return }
        guard let audioInput = try? AVCaptureDeviceInput(device: device) else { return }

        // 2.创建输出源
        let audioOutput = AVCaptureAudioDataOutput()
        let queue = DispatchQueue.global()
        audioOutput.setSampleBufferDelegate(self, queue: queue)

        // 3.将输入&输出添加到会话中
        if session.canAddInput(audioInput) {
            session.addInput(audioInput)
        }
        if session.canAddOutput(audioOutput) {
            session.addOutput(audioOutput)
        }
    }

添加预览图

    // 添加预览图层
    fileprivate func setupPreviewLayer(session : AVCaptureSession) {
        // 1.创建预览图层
        guard let previewLayer = AVCaptureVideoPreviewLayer(session: session) else { return }

        // 2.设置图层的属性
        previewLayer.frame = view.bounds

        // 3.将图层添加到view中
        view.layer.insertSublayer(previewLayer, at: 0)
    }

遵守协议,实现代理方法

extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
        if connection == videoConnect {
            print("视频数据")
        } else {
            print("音频数据")
        }
    }
}

停止扫描

比如用户不再直接,我们需要停止扫描

移除预览图层(不再直播肯定不需要预览图层了)
停止扫描(调用session的stopRunning方法)
将session设置为nil(对象不再使用,指针置空)
    @IBAction func stopScanning() {
        // 1.移除图层
        previewLayer?.removeFromSuperlayer()

        // 2.停止扫描
        session?.stopRunning()

        // 3.将对象重置为nil
        session = nil
    }

切换镜头&聚焦&写入文件

切换镜头(前置&后置摄像头)

切换步骤

给切换过程添加动画
获取当前摄像头是前置还是后置
取出相反的摄像头(之前是前置,这次取出后置)
通过新摄像头重新获取设备(AVCaptureDevice)
通过设备(AVCaptureDevice)创建新的输入(AVCaptureDeviceInput)
移除旧input&添加新的input
注意:修改session配置之前先调用开启修改配置选项,配置完成后,调用提交修改配置选项
session?.beginConfiguration()
session?.commitConfiguration()
保存新的input

图例解析:

图例解析

代码如下:
    @IBAction func switchScene() {
        // 0.执行动画
        let rotaionAnim = CATransition()
        rotaionAnim.type = "oglFlip"
        rotaionAnim.subtype = "fromLeft"
        rotaionAnim.duration = 0.5
        view.layer.add(rotaionAnim, forKey: nil)

        // 1.校验videoInput是否有值
        guard let videoInput = videoInput else { return }

        // 2.获取当前镜头
        let position : AVCaptureDevicePosition = videoInput.device.position == .front ? .back : .front

        // 3.创建新的input
        guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return }
        guard let newDevice = devices.filter({$0.position == position}).first else { return }
        guard let newVideoInput = try? AVCaptureDeviceInput(device: newDevice) else { return }

        // 4.移除旧输入,添加新输入
        session?.beginConfiguration()
        session?.removeInput(videoInput)
        session?.addInput(newVideoInput)
        session?.commitConfiguration()

        // 5.保存新输入
        self.videoInput = newVideoInput
    }

写入文件

写入文件步骤

创建AVCaptureMovieFileOutput对象
用于将音频视频写入文件
将movieFileOutput对象,添加到session的输出中
写入文件也是一种输出
设置视频的稳定模式
不设置可能会出现视频跳帧等问题
通常设置为自动即可
开始写入
录制完成,停止写入即可

代码解析

代码解析

代码如下:
        // 添加文件输出
        let movieFileoutput = AVCaptureMovieFileOutput()
        self.movieFileOutput = movieFileoutput
        session.addOutput(movieFileoutput)
        // 获取视频的connection
        let connection = movieFileoutput.connection(withMediaType: AVMediaTypeVideo)
        // 设置视频的稳定模式
        connection?.preferredVideoStabilizationMode = .auto

        // 开始写入视频
        movieFileoutput.startRecording(toOutputFileURL: outputFileURL, recordingDelegate: self)
停止写入代码
        // 0.停止写入
        self.movieFileOutput?.stopRecording()
在代理方法中监听开始、结束事件
extension ViewController : AVCaptureFileOutputRecordingDelegate {
    func capture(_ captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAt fileURL: URL!, fromConnections connections: [Any]!) {
        print("开始录制")
    }

    func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
        print("停止录制")
    }
}
WebRTC学习二:WebRTC音视频数据采集 在前面的博文《WebRTC获取音视频设备》中,我们介绍了如何利用WebRTC技术来获取本地的音视频设备。本文将在此基础上,进一步探讨如何使用WebRTC进行音视频数据的采集,并实时展示在网页中。我们将通过一个简单的HTML页面和对应的JavaScript代码实现这一功能。通过本文,我们学习了如何使用WebRTC的getUserMedia方法获取音视频设备的数据流,并将其显示在网页上。这是构建实时音视频通信应用的关键步骤之一。在接下来的文章中,我们将继续探讨WebRTC的其它内容,敬请期待! 阅读详情

相关推荐

【音视频学习】二、windows环境下使用Qt6+FFmpeg实现音频采集

本文介绍了在Windows环境下使用Qt和FFmpeg进行音频采集的开发流程。开发环境配置为Win10 64位系统、Qt Creator 17.0.0和FFmpeg 7.1.1。主要内容包括:1)创建Qt项目;2)音频采集流程详解,重点演示了通过FFmpeg API(如avdevice_register_all、avformat_open_input等)打开音频设备的方法;3)音频数据读取与存储,展示了如何通过av_read_frame采集音频帧并保存为PCM文件。文中提供了详细的代码示例,涵盖设备枚举、设

weixin_45414088的博客 2518

Swift开启权限并且拍摄视频

引入AVFoundation 框架 fileprivate lazy var queue = DispatchQueue.global(); fileprivate lazy var audioqueue = DispatchQueue.global(); fileprivate lazy var session = AVCaptureSession(); fileprivate lazy var previewLayer = AVCaptureVideoPreviewLaye.

BianHuanShiZhe的专栏 690

卸载重装Ubuntu22.04双系统

先说一下写此篇文章的背景吧,我在Windows下配置了三个cornerNet深度学习环境分别是cuda10.3(显卡版本太高不支持),cuda11.3(配置后偶然看到一篇说这个版本win下只能用CPU跑),最后是cuda11.1终究还是没能跑通代码,因为它的代码是在Liunx系统写的,就想着装个Ubuntu试试看,在网上看说一般软件不要装太高版本,我就下载了470版的显卡驱动,跟着步骤升级了系统内核,结果第二天开机Ubuntu就崩了,开机黑屏左上角只有一道横杠显示,只能按ctrl+shift+f5进入命令窗

编程小白的博客 8104

swift--获取相机数据流

//所需框架 import AVFoundation 关键 1.输入AVCaptureDevice 2.控制,调整AVCaptureSession 3.输出AVCaptureVideoDataOutput,输出的数据需要实现AVCaptureVideoDataOutputSampleBufferDelegate的captureOutput方法来接收。 4.显示AVCapture...

weixin_41735943的博客 1262

Centos7 XFS(dm-0):Internal error XFS_WANT_CORRUPTED_GOTO

在k8s的道路上我们都是小白,每天启动虚机都会遇到各种各样的问题,这不。部署的k8s虚机启动发现操作系统启动异常,提示如下报错信息。进入/dev/mapper目录下,查询目录下路径信息。可以通过对文件系统进行修复操作,操作如下。重启完成后虚机恢复正常登录。

hedao0515的专栏 4583

[小技巧] 如何复制知乎电子书中的文字和图片

文章目录一、背景二、复制文字1.最简单的方法(适合短小文字)2. 进阶方法(适合大段文字)三、复制图片四、注意事项 一、背景 有时候希望从书中摘录一部分文字作为笔记,但是知乎电子书阅读时候是禁止copy的,要么手打,要么OCR,给学习带来了一些不便。 审查元素后发现,知乎电子书是把文字分成一段一段的,试图F12直接copy不太方便。 本问将以谷歌Chrome浏览器为例,给出复制小技巧。 二、复制文字 1.最简单的方法(适合短小文字) 选中你需要的文字,左键单击不放,直接拖到地址栏。 然后可以从地址栏中

江南蜡笔小新 9246

如何采集视频数据

采集视频数据可以包括从在线视频平台获取视频、摄像头实时采集等。下面是一些通用的步骤和示例代码,具体取决于你的需求和数据源。

D0126_的博客 1796

从ARCore到AICore:揭秘Google如何通过系统级服务推动Android生态创新

本文深入探讨了Google如何通过AICore等系统级服务推动Android生态创新。从ARCore到AICore,Google通过分层解耦策略将AI能力下沉至系统层,实现端侧大模型推理,如Gemini Nano在Pixel 8 Pro中的应用。文章剖析了AICore的技术架构、开发者赋能路径及场景化实践,展示了其在通信、内容创作和生产力工具中的卓越表现。

rust6ferris的博客 545

直播入门(二)从视频采集到客户端播放

概述 一个主播开播到用户能观看,一共经历了以下几个过程: 采集:通过摄像头,麦克风等采集图像和音频数据 编码:将采集到音频和图像数据,编码压缩,降低数据大小,并尽可能的保留精度。 封装:将编码后的数据,封装成各个格式,大家比较熟悉的如:FLV,MP4 推流:将完成封装的数据,采用HTTP或者RTMP协议推送到服务端 分发:直播流服务将数据分发给各个客户端,也就是每个用户的浏览器或App上。 播放...

waponx的专栏 4546

华南理工大学电子与信息学院23年预推免复试面试经验贴

华南理工大学电子与信息学院23年预推免复试面试经验贴

Scut_Ty的博客 3295

uniApp微信小程序:error: 60001 request:fail errcode:-101 cronet error code:-101error_msg:net::ERR CONNECTI

uni-app微信小程序域名访问报error 60001 request:fail errcode:-101,解决Uniapp微信小程序报600001错误,uni.request()接口请求报错,服务器更换SSL证书后,uniapp微信小程序出现`request:fail errcode:-101`问题分析与解决,服务器更换ssl证书后,手机访问微信小程序异常,微信小程序更换SSL证书后出现请求报错,服务器更换SSL证书,微信小程序报600001,小程序反应偶尔出现request:fail errcode:

✅ 精选推荐文章 4580

OpenCV_python(二)视频的采集与存储

1.视频采集 import numpy as np import cv2 as cv cap=cv.ViedoCapture(0) #当有多个摄像头时,改变参数1,2... while(cap.isOpened()): ret,frame=cap.read() #ret返回布尔类型的数值,当摄像头成功捕获图像时,返回True,否则False #frame返回采集的一帧图像 cv.imshow("frame",frame) if cv.waitKey(1) & OxFF ==ord('q')

fjzxqm的博客 1071

YOLOv13保姆级教程+AKConv模块:可变形卷积+自适应核优化,mAP提升3.23%,召回率&mAP50~95显著提升(论文涨点模块已验证)

本文介绍了一种改进的YOLOv13-AKConv模型,通过引入AKConv模块显著提升了目标检测性能。实验结果表明,优化后的模型(绿色曲线)相比原模型(蓝色曲线)在mAP指标上提升了3.23个点,同时召回率、mAP50-95等指标均有明显提升。作者详细阐述了模型移植过程,包括创建yolov13-AKConv.yaml配置文件,修改tasks.py和modules/init.py文件,以及实现AKConv模块的核心代码。该模块采用可变形卷积思想,通过动态生成采样点位置来增强特征提取能力,并集成了BN和SiLU

FJN110的博客 2611

webrtc中视频采集实现分析(二) 视频帧的分发

视频采集模块,抛出视频数据后,对视频帧的处理需求一般包括如下几种: 视频帧送到编码模块进行编码 视频帧送到渲染模块进行本地回显 视频帧先进行预处理(比如添加水印,字幕),再送去回显或编码 视频帧会送到多个编码器,产生多路不同分辨率,码率的码流 所以从采集模块获取的视频帧是需要分发的,也是只有一个source,但是有多个sink webrtc中的实现 webrtc中有一个对视频帧的分发框架,可以直接借用 相关实现 videoSourceInterface 作为source的基类 主要接口是 AddOrU

mo4776的博客 3211

学Simulink--进阶电机控制场景实例:基于Simulink的异步电机定子磁链定向控制(SFOC)仿真

本文详细介绍了基于Simulink的异步电机定子磁链定向控制(SFOC)仿真实现方法。主要内容包括:1) SFOC原理分析,突出其对转子参数不敏感的优势;2) 工业风机驱动系统的完整建模流程,涵盖主电路搭建、坐标变换、磁链观测器设计等关键步骤;3) 核心模块代码实现,包括电压模型磁链观测器和双闭环PI控制器;4) 仿真结果验证了SFOC在转速响应(0.2s)、转矩恢复(0.15s)和参数鲁棒性(转子电阻变化50%时转速波动<2%)方面的优异性能。本文为工程师提供了实用的SFOC系统开发指南,特别适用于

amy_mhd的博客 116

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

用DirectShow实现视频采集(二)

3.具体实现首先我们需要创建几个接口全局变量。IGraphBuilder *pGraph; //过滤器图表管理器ICaptureGraphBuilder2 *pBuild; //视频采集过滤器图表IBaseFilter *pCap; //Video Capture FilterIBaseFilter *pSmartTee; //Smart Tee FilterIBaseFilter *pRende...

wmnmtm的专栏 230

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Matorx视频采集卡开发及使用(二)

本文初始目的为购买Matrox视频采集卡,用于采集Basker相机视频图像,接口为cameraLink。采集卡版本为ev-cl。

nannanstyle的博客 1272

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

iOS视频采集(二)

音视频采集(二) 对(一)进行重构 在info.plist添加两个访问项 在(一)基础上添加音频采集

targetcloud 550

实时音视频的那些事儿(二)—— 音频采集

总的来说,iOS端的音频采集可以基于AVFoundation提供的AVAudioRecorder类进行简单的录音操作,也可以使用Core Audio框架中的Audio Unit实现低延时、高质量的音频采集和处理,具体实现方式需要根据应用场景和需求进行选择。需要注意的是,音频采集过程中需要申请权限,并且考虑到设备的不同,配置参数和实现方式会有所不同。需要注意的是,这里采集到的是PCM格式的音频数据,需要根据采集参数进行相应的解析。4. 停止音频采集 在不需要采集音频数据时,需要调用AudioRecord的。

weixin_42684521的博客 1571

OV511视频采集设计文档 (二)

作者:曾永刚 转自:http://zyg0227.blog.51cto.com/1043164/316940 4.   视频编程流程及函数实现 (1)打开视频设备和输出文件:                      char *devicename="/dev/video0";        if((vd->fd = open(devicename,O_RDWR

老瓦的笔记本 629

实验二:基于PyQT6的视频人物面部采集与标注系统

path, _ = QFileDialog.getOpenFileName(self, "选择视频文件", "", "视频文件 (*.mp4 *.avi)")self.status_label.setText(f"已加载视频: {os.path.basename(path)}")self.status_label.setText(f"已保存: {image_filename}")self.path_label.setText(f"保存路径: {path}")

2401_89522201的博客 922

Python 笔记(二) 采集保存某牙视频

采集保存某牙视频

Ggome的博客 244

iOS直播(二)GPUImage音视频采集

GPUImage是一个开源的基于GPU的第三方图像处理库,可以对图像进行美化、添加各种滤镜等。GPUImage的视频采集部分的源代码,也是和上文中的AVFoundation实现采集(https://blog.youkuaiyun.com/dolacmeng/article/details/81268622)的步骤是一致的。下面例子是进行视频采集并添加增亮滤镜: 1.用cocoapods集成。 (1)用Xc...

dolacmeng的专栏 906

OpenCV+多线程视频采集(二)

一、在完成OpenCV+多线程视频采集(一)后,我们可以改用moveToThread函数来实现多线程,不需要从OThread继承它,创建一个新类VidoProcessor;

mirror360的博客 265
上一篇: 直播总体概览(一)
下一篇: LXR_CHNGroup自定义分组与系统通讯录分组
XR_Code
博客等级 码龄10年 16粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值