C#实现视频会议录制(支持Windows、Linux、银河麒麟、统信UOS)

随着远程办公与异地协作越来越频繁,视频会议系统的使用也是越来越普遍。同时,用户对视频会议系统的功能也提出了更高的要求,比如,其中之一就是希望可以将整个视频会议的过程录制下来,以备之后可以查阅观看。

我们可以选择在视频会议系统的服务端或客户端来录制整个视频会议过程,在服务端录制与在客户端录制各有优劣。比如,在服务端录制对服务器配置要求更高,因为同时可能有很多个会议同时录制;而在客户端录制,录制的文件存放在客户端本地电脑上,只能在本地播放,如果其他人需要观看,则需要在录制完成后将该文件再上传到服务器。

无论是在服务端录制,还是在客户端录制,其技术原理是一样的。这里我就傲瑞视频会议在服务端(Windows、Linux、信创国产OS、银河麒麟、统信UOS)录制会议过程的技术原理和实现介绍给大家。

如下图就是某会议录制文件使用QQ影音播放的效果:

接下来,我们将具体介绍傲瑞视频会议是怎么实现会议录制的。

一. 录制流程说明

(1)会议信息中心包含了一个字段,用于指示该会议是否开启录制。

(2)当第一个人进入会议时,启动录制。

(3)当到会议结束时间:若会议室没有人,这立即结束录制;若会议室还有人,等最后一个人退出时,结束录制。

(3)任何时候,主持人结束会议,则将同时结束录制。

(4)中途若会议室没有人时,则暂停录制;当再有人进入会议时,则继续录制。

二. 傲瑞会议录制的画面布局

(1)录制画面最上面有一行高为30px标题栏,将实时显示如下信息:会议名称、系统时间、参会人数。

(2)标题栏下面的剩下区域为内容区,用来渲染用户视频/头像,或者是渲染用户分享屏幕的桌面图像。

(3)当参会人数不超过4个人时,采用2x2四宫格;当参会人数多于4个人时,采用3x3九宫格。

(4)录制时最多渲染9个人的视频或头像(3x3),开启了视频的用户排在最前面,其次是开启了麦克风的用户。

(5)如果用户开启了视频,录制时就渲染其视频图像,否则,就渲染该用户的默认头像。

(6)如果参会人员中有人开启了屏幕分享,这录制画面的内容区将不再渲染用户视频/头像,而是改为渲染被分享屏幕的桌面图像。

三. 程序实现技术要点

(1)获取参会人员的PCM声音数据和RGB图像数据。

使用 OMCS 提供的 MicrophoneConnector 和 DynamicCameraConnector 就可以获取每个参会人员的声音数据以及图像数据。

(2)拼接并渲染要录制的视频图像帧

在Windows可使用GDI+技术、在Linux上则可使用Skia技术来完成录制图像帧的拼接渲染。

if (desktopShare) //如果有人分享桌面,这主体内容区就是桌面图像
{
    //获取屏幕分享的最新桌面图像帧
    Image image = this.connectorManager.GetCurrentImage(null);
    canvas.SetDesktopImage(image);
}
else
{
    for (int i = 0; i < recordMembers.Count; i++)
    {
        string userID = recordMembers[i];
        Image image = null;
        if (!meeting.CamClosedMemberList.Contains(userID))
        {
            //获取参会成员的最新视频图像帧
            image = this.connectorManager.GetCurrentImage(userID);
        }
        
        DrawInfo renderModel = this.drawInfoManagers.Get(userID);
        renderModel.SetCameraImage(image);
        renderModel.SetMicState(!meeting.MuteMemberList.Contains(userID));
    }
    //绘制主体内容区
    canvas.SetCameraImage(this.drawInfoManagers.GetAll());
}
byte[] bytes = canvas.RenderImage(); //准备好要录制的图像
if (bytes != null)
{
    this.videoFileMaker?.AddVideoFrame(bytes); //提交给录制器    
}

(3)混音

使用 OMCS 提供的 MicrophoneConnectorMixer 可以将参会人员的声音混成一路。

IConnectorManager connectorManager = new OMCSConnectorManager(globalCache);
connectorManager.AudioMixed += ConnectorManager_AudioMixed;

private void ConnectorManager_AudioMixed(string userID, byte[] data)
{
    if (recording && data != null)
    {
        this.videoFileMaker?.AddAudioFrame(data);  //将混音数据提交给录制器        
    }
}

(4)定时器

使用定时器来调度声音数据和图像数据。比如:每隔10毫秒就从各个MicrophoneConnector获取一帧语音数据,并将它们混音。每隔40毫秒就从各个 DynamicCameraConnector 获取相应的图像数据,并将它们拼接,并按照前面描述的画面布局进行渲染。

//开启录制线程,定时调用
internal void StartRecord()
{
    recording = true;
    Task.Factory.StartNew(() =>
    {
        RecordThread();
    });
}

private void RecordThread()
{
    int sleepSeconds = 1000 / frameRate;
    while (true)
    {
        System.Threading.Thread.Sleep(sleepSeconds);
        //record ...
    }
}

(5)将图像帧和声音帧编码并生成MP4文件。

将混音好的声音数据、拼接好的渲染图像提交给MFile,MFile会将它们编码并写入到MP4文件中。

会议结束时,将结束录制,并释放相关的资源。

internal void FinishRecord()
{
    recording = false;
    //释放麦克风、摄像头、桌面设备连接器
    connectorManager.DisconnectAllConnect();
    //释放录制器
    videoFileMaker?.Close(true);
}

四. 结语

在将录制会议的流程、画面布局、技术要点做了简单介绍后,相信大家对视频会议服务端在程序上是如何实现会议录制功能的,已经初步了解了。

本文只是粗略地介绍了视频会议录制的原理与技术实现,如果你有更具体的实现细节需要了解的,欢迎与我讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904928.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

树莓派开发相关知识四 传感器-温湿度传感器

1、概述 使用DHT11温湿度传感器&#xff0c;传感周期为1s。 DHT11模块一般由3/4个引脚组成&#xff0c;每一次收集数据为40bit。 分别为&#xff1a; 高位在前、8bit湿度整数数据8bit湿度小数数据8bi温度整数数据8bit温度小数数据8bit校验和 我们需要解决的问题&#xff0c;…

vue3+less使用主题定制(多主题定制)可切换主题

假如要使用两套主题&#xff1a;蓝色、红色 例如&#xff1a; 首先确保自己的vue3项目有less&#xff0c;这边不多做接入解释 1、在src目录下建一个styles文件夹&#xff0c;在syles文件夹下面新建两个less文件&#xff1a;theme.less和variables.less&#xff1b; theme.le…

Spring Cloud Sleuth(Micrometer Tracing +Zipkin)

分布式链路追踪 分布式链路追踪技术要解决的问题&#xff0c;分布式链路追踪&#xff08;Distributed Tracing&#xff09;&#xff0c;就是将一次分布式请求还原成调用链路&#xff0c;进行日志记录&#xff0c;性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节…

春季测试 2023 我的题解

T1 涂色游戏 这道题目还是比较简单的 容易发现&#xff0c;位于 ( x i , y i ) (x_i,y_i) (xi​,yi​) 的格子的颜色只取决于 ​ x i x_i xi​ 行与 y i y_i yi​ 列的颜色。 这时候可以想到开两个数组&#xff0c;分别存储列与行的绘画信息&#xff0c;然后发现前后的互相…

Kali Linux 新工具推荐: Sploitscan

在 2024.2 版本 Kali Linux 增加了一个新攻击工具: Sploitscan 1.简介: Sploitscan 能够发现操作系统和应用程序中的安全漏洞。 2.特点: 简单的命令行界面 扫描多个操作系统和应用程序 检测多种漏洞 提供详细信息 可定制性强 3.示例: 2024.2 及以后的版本 Kali Linux…

【JAVA 笔记】09 ch06_arrays_sort_and_search

第6章 数组、排序和查找 数组介绍 数组的使用 使用方式1-动态初始化数组的定义 使用方式2-动态初始化 使用方式3-静态初始化 数组使用注意事项和细节 数组应用案例 数组赋值机制 数组拷贝 数组添加/扩容 多维数组 二维数组 动态初始化1 动态初始化2 静态初始化 二维数组的应用案…

C语言实现归并排序

#include <stdio.h> #include <stdlib.h> #include<time.h> #include<string.h> #define N 7 // 定义元素类型为整型 typedef int ElemType; // 定义静态表结构体 typedef struct{ ElemType *elem; // 动态分配的数组指针 int TableL…

第十八章 Vue组件样式范围配置之scoped

目录 一、引言 二、案例演示 2.1. 工程结构图 2.2. 核心代码 2.2.1. main.js 2.2.2. App.vue 2.2.3. BaseOne.vue 2.2.4. BaseTwo.vue 2.3. 运行效果 2.4. 调整代码 2.4.1. BaseTwo.vue 2.4.2. 运行效果 三、scoped原理 一、引言 前面的几个章节在介绍组件的时…

Linux 中,flock 对文件加锁

在Linux中&#xff0c;flock是一个用于对文件加锁的实用程序&#xff0c;它可以帮助协调多个进程对同一个文件的访问&#xff0c;避免出现数据不一致或冲突等问题。以下是对flock的详细介绍&#xff1a; 基本原理 flock通过在文件上设置锁来控制多个进程对该文件的并发访问。…

stm32入门教程-- DMA数据转运

目录 简介 原理 实验示例 1、DMA数据转运 实现代码 实验效果 原理 实验示例 1、DMA数据转运 接线图 存储器映像 我们在开始代码之前&#xff0c;可以看下我们定义的数据&#xff0c;到底是不是真的存储在了这个相应的地址区间里&#xff0c;我们看代码&#xff1a; …

SELS-SSL/TLS

一、了解公钥加密&#xff08;非对称加密&#xff09; 非对称加密中&#xff0c;用于加密数据的密钥与用于解密数据的密钥不同。私钥仅所有者知晓&#xff0c;而公钥则可自由分发。发送方使用接收方的公钥对数据进行加密&#xff0c;数据仅能使用相应的私钥进行解密。 你可以将…

【Kettle的安装与使用】使用Kettle实现mysql和hive的数据传输(使用Kettle将mysql数据导入hive、将hive数据导入mysql)

文章目录 一、安装1、解压2、修改字符集3、启动 二、实战1、将hive数据导入mysql2、将mysql数据导入到hive 一、安装 Kettle的安装包在文章结尾 1、解压 在windows中解压到一个非中文路径下 2、修改字符集 修改 spoon.bat 文件 "-Dfile.encodingUTF-8"3、启动…

【机器学习】 15. SVM 支撑向量机 support vector machine,拉格朗日,软边界,核函数

SVM 支撑向量机 support vector machine&#xff0c;拉格朗日&#xff0c;软边界&#xff0c;核函数 1. 超平面边界 margin of hyperplane2. 边界越大的超平面越好原因 3. 线性模型通过决策边界分类4. SVM的问题5. 拉格朗日乘子与SVM结合求最大边界6. SVM软边界和硬边界7. 非线…

多线程学习篇六:park / unpark

1. API LockSupport.park()&#xff1a;暂停当前线程LockSupport.unpark (线程对象)&#xff1a;恢复某个线程的运行 1.1 先 park 再 unpark main 线程睡眠时间大于 t1 线程睡眠时间 Slf4j(topic "c.Test01") public class Test01 {public static void main(Str…

传承双百基因 大将军F9轻松跑“盈”脐橙创富路

“江作青罗带&#xff0c;山如碧玉簪。”广西河池&#xff0c;地处桂林西北一隅&#xff0c;奇秀的喀斯特地貌纵横绵延&#xff0c;亚热带季风气候温润宜人&#xff0c;堪称种植脐橙的“天选之地”。 正值秋季&#xff0c;这里漫山遍野&#xff0c;“橙”香四溢&#xff0c;大量…

一图看懂亚信安全2024年三季度财报

一图看懂亚信安全2024年三季度财报&#xff0c; 2024年前三季度营收创历史新高&#xff0c; 净利润、经营现金流加速增长&#xff01; &#xff08;相关信息主要摘自亚信安全2024年三季度财报&#xff0c; 如存在差异&#xff0c;以亚信安全2024年三季度财报为准。&#xff0…

arm 体系架构-过程调用标准AAPCS

一、什么是AAPCS&#xff1f; 旧时&#xff0c;ARM 过程调用标准叫做 APCS (ARM Procedure Call Standard)&#xff0c;Thumb的过程调用标准为 TPCS。如今这两种叫法已经废弃&#xff0c;统一称作 AAPCS (Procedure Call Standard for the ARM Architecture)。 AAPCS 是 ARM …

Kubernetes运行大数据组件-运行spark

部署组件 ● spark-historyserver ● spark-client 配置文件 kind: ConfigMap apiVersion: v1 metadata:name: spark data:spark-defaults.conf: |-spark.eventLog.enabled truespark.eventLog.dir hdfs://192.168.199.56:8020/eventLogsspark.ev…

STM32FreeRTOS 使用QSPI驱动nandFlash

STM32FreeRTOS 使用QSPI驱动nandFlash 不清楚为什么STM32同时打开3个以上的音频文件时会出现播放问题&#xff0c;所以更换方案。因为SRAM的内存空间过小&#xff0c;用于存储音频文件不适合&#xff0c;所以使用大小为128MByte的nandFlash。 nandFlash使用华邦的W25N01GVZEI…

Nature Communications|综述|无线胶囊内窥镜机器人的最新研究进展和未来发展方向(健康监测/柔性传感/可吞服电子)

浙江大学杨华勇(Huayong Yang)院士和韩冬( Dong Han)特聘研究员团队,在期刊《Nature Communications》上发布了一篇题为“Robotic wireless capsule endoscopy: recent advances and upcoming technologies”的综述论文,博士生曹青(Qing Cao)为论文第一作者。综述内容如…