音视频-视频录制编程
2021-07-14 本文已影响0人
li_礼光
Mac下ffmpeg视频录制
ffmpeg -f avfoundation -framerate 30 -i 0 out.yuv
Mac下ffmpeg音频录制
ffmpeg -f avfoundation -i :0 out.wav
对比命令行的录制音频和视频. 其实可以猜得到, 视频录制编程 跟音视频-ffmpeg录制PCM是一样的思路的.
主要步骤
注册设备 avdevice_register_all();
获取输入格式对象 av_find_input_format
打开设备 avformat_open_input
采集数据 av_read_frame
释放资源 avformat_close_input
Mac平台添加info
<key>NSCameraUsageDescription</key>
<string>申请使用摄像头进行录制</string>
如果添加了还报错, 删除之前编译好的工程.
可能会遇到的格式支持方案的报错
[avfoundation @ 0x10c0c5600] Selected framerate (29.970030) is not supported by the device.
[avfoundation @ 0x10c0c5600] Supported modes:
[avfoundation @ 0x10c0c5600] 1280x720@[1.000000 30.000000]fps
[avfoundation @ 0x10c0c5600] 1280x720@[1.000000 30.000000]fps
[avfoundation @ 0x10c0c5600] 1280x720@[1.000000 30.000000]fps
设置符合规则的像素格式和视频大小, 如何设置
通过API的注释中搜索, 可以搜索关键字"pixel_format" 或者是"pixel", 像素格式可以发现
* @code
* AVDictionary *options = NULL;
* av_dict_set(&options, "video_size", "640x480", 0);
* av_dict_set(&options, "pixel_format", "rgb24", 0);
*
* if (avformat_open_input(&s, url, NULL, &options) < 0)
* abort();
* av_dict_free(&options);
就知道了怎么设置视频参数格式
代码实现
// 格式名称,设备名称
#ifdef Q_OS_WIN
// todo win下的配置根据电脑来, 因为win没有摄像头, 用Mac的来实现先
#else
#define FMT_NAME "avfoundation"
#define DEVICE_NAME "0"
#define FILEPATH "/Users/liliguang/Desktop/"
#define FILENAME "record_to_yuv.yuv"
#define VEDIO_SIZE "1280x720"
#define FRAMERATE "30"
#define PIXEL_FORMAT "uyvy422"
#endif
void VedioThread::run() {
qDebug() << this << "开始执行----------";
// 获取输入格式对象
AVInputFormat *fmt = av_find_input_format(FMT_NAME);
if (!fmt) {
qDebug() << "获取输入格式对象失败" << FMT_NAME;
return;
}
qDebug() << "fmt : " << fmt;
// 格式上下文(将来可以利用上下文操作设备)
AVFormatContext *ctx = nullptr;
AVDictionary *options = NULL;
av_dict_set(&options, "video_size", VEDIO_SIZE, 0);
av_dict_set(&options, "framerate", FRAMERATE, 0);
av_dict_set(&options, "pixel_format", PIXEL_FORMAT , 0);
// 打开设备
int ret = avformat_open_input(&ctx, DEVICE_NAME, fmt, &options);
if (ret < 0) {
char errbuf[1024];
av_strerror(ret, errbuf, sizeof (errbuf));
qDebug() << "打开设备失败" << errbuf;
return;
}
qDebug() << "ret : " << ret;
// 文件名
QString filename = FILEPATH;
filename += FILENAME;
QFile file(filename);
if (!file.open(QFile::WriteOnly)) {
qDebug() << "文件打开失败" << filename;
// 关闭设备
avformat_close_input(&ctx);
return;
}
// 数据包
AVPacket pkt;
while (!isInterruptionRequested()) {
// 不断采集数据
ret = av_read_frame(ctx, &pkt);
if (ret == 0) { // 读取成功
// 将数据写入文件
file.write((const char *) pkt.data, pkt.size);
} else if (ret == AVERROR(EAGAIN)) { // 资源临时不可用
continue;
} else { // 其他错误
char errbuf[1024];
av_strerror(ret, errbuf, sizeof (errbuf));
qDebug() << "av_read_frame error" << errbuf << ret;
break;
}
}
// 释放资源
// 关闭文件
file.close();
// 关闭设备
avformat_close_input(&ctx);
qDebug() << this << "正常结束----------";
}
正常输出:
2021-07-14 23:30:40.838608+0800 9_record_to_yuv[10634:364232] VedioThread(0x12583ba30) 开始执行----------
2021-07-14 23:30:40.838828+0800 9_record_to_yuv[10634:364232] fmt : 0x10166fac0
2021-07-14 23:30:40.841558+0800 9_record_to_yuv[10634:364232] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x1097673c0> F8BB1C28-BAE8-11D6-9C31-00039315CD46
2021-07-14 23:30:40.865234+0800 9_record_to_yuv[10634:364232] HALC_ShellDriverPlugIn::Open: Can't get a pointer to the Open routine
2021-07-14 23:30:40.865519+0800 9_record_to_yuv[10634:364232] HALC_ShellDriverPlugIn::Open: Can't get a pointer to the Open routine
2021-07-14 23:30:40.886784+0800 9_record_to_yuv[10634:364232] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x12583f000> 30010C1C-93BF-11D8-8B5B-000A95AF9C6A
2021-07-14 23:30:43.274195+0800 9_record_to_yuv[10634:364232] ret : 0
2021-07-14 23:30:56.460552+0800 9_record_to_yuv[10634:364232] [] CMIO_DAL_PlugIn.cpp:269:StreamCopyBufferQueue Error: 1852797029, got an error from the plug-in routine
2021-07-14 23:30:56.464971+0800 9_record_to_yuv[10634:364232] VedioThread(0x12583ba30) 正常结束----------
2021-07-14 23:30:56.465248+0800 9_record_to_yuv[10634:364047] VedioThread(0x12583ba30) 析构(内存被回收)
使用FFmpeg命令行播放
ffplay -video_size 1280x720 -pixel_format uyvy422 -framerate 30 record_to_yuv.yuv
自测播放正常