自定义视频采集
自定义视频采集是指通过自定义的视频采集源实现视频采集。
与 SDK 默认的视频采集方式不同,自定义视频采集支持用户自行控制采集源,实现更加精细的视频属性调整。例如,支持通过高清摄像头、无人机摄像头或其他类型的摄像头实现视频采集,同时支持动态调整视频质量、分辨率和帧率等参数,以适应不同的应用场景和需求。
声网推荐优先使用更为稳定、可靠、集成维护难度低的 SDK 视频采集,如果你有特定的视频采集需求或无法使用 SDK 采集,那么自定义视频采集为你提供灵活、可定制的方案。
技术原理
声网 SDK 提供自定义视频轨道方式实现视频自采集。你可以创建一个或多个自定义视频轨道,加入频道并在每个频道中发布已创建的视频轨道。你需要使用自采集模块驱动采集设备对视频进行采集,并将采集的视频帧通过视频轨道发送给 SDK。
下图展示在单频道和多频道中实现自定义视频采集时,视频数据的传输过程:
仅在一个频道内发布自采集视频流:
在多个频道内发布不同的自采集视频流:
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能,详见实现音视频互动。
实现自定义视频采集
下图展示实现自定义视频采集的流程:
参考如下步骤,在你的 App 中实现自定义视频采集功能:
1. 创建自定义视频轨道
初始化 IRtcEngine
后,调用 CreateCustomVideoTrack
创建自定义视频轨道并获得视频轨道 ID。根据场景需要,你可以创建多个自定义视频轨道。
private uint _videoTrack;
private void CreateCustomVideoTrack()
{
_videoTrack = RtcEngine.CreateCustomVideoTrack();
this.Log.UpdateLog("CreateCustomVideoTrack returns:" + _videoTrack);
}
2. 加入频道并发布自定义视频轨道
调用 JoinChannel
[2/2] 加入频道,或调用 JoinChannelEx
加入多频道, 在每个频道的 ChannelMediaOptions
中,将 customVideoTrackId
参数设置为步骤 1 中获得的视频轨道 ID,并将 publishCustomVideoTrack
设置为 true
,即可在频道中发布指定的自定义视频轨道。
加入单频道:
private void JoinChannel()
{
RtcEngine.EnableAudio();
RtcEngine.EnableVideo();
RtcEngine.SetClientRole(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
ChannelMediaOptions options = new ChannelMediaOptions();
options.publishCameraTrack.SetValue(false);
// 发布自采集的视频流
options.publishCustomVideoTrack.SetValue(true);
// 设置自定义视频轨道的 ID
options.customVideoTrackId.SetValue(_videoTrack);
// 加入频道
RtcEngine.JoinChannel(_token, _channelName, 0, options);
}
加入多频道:
private void JoinChannelEx()
{
RtcEngine.EnableAudio();
RtcEngine.EnableVideo();
// 创建自定义视频轨道
uint videoTrack1 = RtcEngine.CreateCustomVideoTrack();
ChannelMediaOptions options = new ChannelMediaOptions();
options.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
options.publishCameraTrack.SetValue(false);
// 发布自采集视频流
options.publishCustomVideoTrack.SetValue(true);
// 设置自定义视频轨道 ID
options.customVideoTrackId.SetValue(videoTrack1);
options.autoSubscribeAudio.SetValue(false);
options.autoSubscribeVideo.SetValue(false);
// 加入频道 1
RtcEngine.JoinChannelEx(_token, new RtcConnection("channel_id_1", 123), options);
// 创建自定义视频轨道
uint videoTrack2 = RtcEngine.CreateCustomVideoTrack();
// 在多个频道发布自定义视频轨道需要多次设置 ChannelMediaOptions 并多次调用 joinChannelEx
ChannelMediaOptions options2 = new ChannelMediaOptions();
options2.clientRoleType.SetValue(CLIENT_ROLE_TYPE.CLIENT_ROLE_BROADCASTER);
options2.publishCameraTrack.SetValue(false);
// 发布自采集视频流
options2.publishCustomVideoTrack.SetValue(true);
// 设置自定义视频轨道 ID
options2.customVideoTrackId.SetValue(videoTrack2);
options2.autoSubscribeAudio.SetValue(false);
options2.autoSubscribeVideo.SetValue(false);
// 加入频道 2
RtcEngine.JoinChannelEx(_token, new RtcConnection("channel_id_2", 123), options2);
}
3. 实现自采集模块
声网提供 CustomCaptureVideo 示例项目演示通过 Unity 的 WebCamTexture 实现采集摄像头数据。在实际的生产环境中,你需要结合业务需求为你的采集设备创建自定义视频采集模块。
private WebCamTexture _webCameraTexture;
public RawImage RawImage;
public Vector2 CameraSize = new Vector2(640, 480);
public int CameraFPS = 15;
private void InitCameraDevice()
{
// 获取所有可用的摄像头设备
WebCamDevice[] devices = WebCamTexture.devices;
// 使用第一个摄像头设备初始化 WebCamTexture 对象,并设置分辨率和帧率
_webCameraTexture = new WebCamTexture(devices[0].name, (int)CameraSize.x, (int)CameraSize.y, CameraFPS);
// 将摄像头纹理赋值给 RawImage 的纹理属性,以便显示摄像头图像
RawImage.texture = _webCameraTexture;
// 开始播放摄像头捕获的图像
_webCameraTexture.Play();
}
4. 通过视频轨道推送视频数据到 SDK
调用 PushVideoFrame
将采集到的视频帧通过视频轨道推送至 SDK。其中, _videoTrack
要与步骤 2 加入频道时指定视频轨道 ID 一致,videoFrame
中可以设置视频帧的像素格式、数据类型和时间戳等参数。
为确保音视频同步,声网建议你将 videoFrame
的时间戳参数设置为系统 Monotonic Time。你可以调用 getCurrentMonotonicTimeInMs
获取当前的 Monotonic Time。
private Texture2D _texture;
private Rect _rect;
private byte[] _shareData;
//初始化一个跟当前屏幕大小一致的 Texture2D 对象用来截屏
private void InitTexture()
{
_rect = new UnityEngine.Rect(0, 0, Screen.width, Screen.height);
_texture = new Texture2D((int)_rect.width, (int)_rect.height, TextureFormat.RGBA32, false);
}
//每帧截屏一次,并将截屏获得的视频数据推送给 SDK
private void Update()
{
StartCoroutine(ShareScreen());
}
private IEnumerator ShareScreen()
{
yield return new WaitForEndOfFrame();
IRtcEngine rtc = Agora.Rtc.RtcEngine.Instance;
if (rtc != null)
{
_texture.ReadPixels(_rect, 0, 0);
_texture.Apply();
#if UNITY_2018_1_OR_NEWER
NativeArray<byte> nativeByteArray = _texture.GetRawTextureData<byte>();
if (_shareData == null || _shareData.Length != nativeByteArray.Length)
{
_shareData = new byte[nativeByteArray.Length];
}
nativeByteArray.CopyTo(_shareData);
#else
_shareData = _texture.GetRawTextureData();
#endif
// 设置推送的自采集视频的编码属性
ExternalVideoFrame externalVideoFrame = new ExternalVideoFrame();
// 设置视频数据类型为原始数据
externalVideoFrame.type = VIDEO_BUFFER_TYPE.VIDEO_BUFFER_RAW_DATA;
// 设置视频格式为 RGBA
externalVideoFrame.format = VIDEO_PIXEL_FORMAT.VIDEO_PIXEL_RGBA;
externalVideoFrame.buffer = _shareData;
externalVideoFrame.stride = (int)_rect.width;
externalVideoFrame.height = (int)_rect.height;
externalVideoFrame.cropLeft = 10;
externalVideoFrame.cropTop = 10;
externalVideoFrame.cropRight = 10;
externalVideoFrame.cropBottom = 10;
externalVideoFrame.rotation = 180;
externalVideoFrame.timestamp = System.DateTime.Now.Ticks / 10000;
// 推送视频帧至 SDK
var ret = rtc.PushVideoFrame(externalVideoFrame, _videoTrack);
Debug.Log("PushVideoFrame ret = " + ret + "time: " + System.DateTime.Now.Millisecond);
}
}
5. 销毁自定义视频轨道并离开频道
如果你需要停止发布自定义采集的视频,调用 DestroyCustomVideoTrack
销毁视频轨道。如需销毁多个视频轨道,可多次调用 DestroyCustomVideoTrack
。
private void OnDestroy()
{
Debug.Log("OnDestroy");
if (_webCameraTexture)
{
_webCameraTexture.Stop();
}
if (RtcEngine == null) return;
// 取消注册频道事件
RtcEngine.InitEventHandler(null);
// 离开频道
RtcEngine.LeaveChannel();
// 销毁自定义视频轨道
RtcEngine.DestroyCustomVideoTrack(_videoTrack);
// 销毁引擎对象,释放所有资源
RtcEngine.Dispose();
}
参考信息
适用场景
你可以在多种行业的多种场景下使用到自定义视频采集:
视频特殊处理和增强
在某些游戏或虚拟现实应用中,需要对视频流进行实时的特效处理、滤镜处理或其他增强效果。在这种情况下,使用自定义视频采集可以直接获取原始视频流,并进行实时处理,从而实现更加逼真的游戏或虚拟现实效果。
高精度视频采集
在视频监控领域,需要对场景中的细节进行精细的观察和分析,此时使用自定义视频采集可以获得更高的图像质量和更精细的采集控制。
特定视频源采集
在 IoT、直播等行业需要使用特定的摄像头、监控设备或其他非摄像头设备视频源,例如视频捕捉卡、录屏数据等。在这种情况下,使用 SDK 内部采集可能无法满足需求,必须使用自定义视频采集来实现对特定视频源的采集。
与特定设备或第三方应用无缝对接
在智能家居或物联网领域,需要将设备中的视频传输到用户的手机或电脑上进行监控和控制,此时可能需要使用特定的设备或应用程序进行视频采集。在这种情况下,使用自定义视频采集可以方便地将特定设备或应用程序与 RTC SDK 进行对接。
特定的视频编码格式
在特定直播场景中,可能需要使用特定的视频编码格式来满足业务需求,此时使用 SDK 内部采集可能无法满足需求,必须使用自定义视频采集来实现对特定编码格式视频的采集和自定义编码。
优势介绍
使用自定义视频采集,你可以体验到:
更多类型的视频流
自定义视频采集功能可以使用更高质量、更多类型的采集设备和摄像头,从而获得更清晰、更流畅的视频流。这有助于提高用户的观看体验,并使产品更具竞争力。
更灵活的视频特效
自定义视频采集功能可以帮助用户实现更丰富、更个性化的视频特效和过滤器,从而提高用户的体验和应用程序的吸引力。用户可以通过自定义视频采集功能实现各种特效,如美颜、滤镜、动态贴纸等。
更适应各种场景的需求
自定义视频采集功能可以帮助应用程序更好地适应各种场景的需求,如直播、视频会议、在线教育等。用户可以根据不同的场景需求,定制不同的视频采集方案,从而提供适应性更强的应用程序。
注意事项
如果采集到的自定义视频格式为 Texture,并且远端用户看到的自定义采集视频画面出现闪烁、失真等异常情况时,建议先复制视频数据,再将原始视频数据和复制的视频数据发回至 SDK,从而消除内部数据编码过程中出现的异常情况。
示例项目
声网提供了开源的视频自采集示例项目供你参考,你可以前往下载或查看其中的源代码。