傲瑞组件FAQ -- 傲瑞组件常见问题解答
关于在使用语音视频录制组件MFile、采集组件MCapture的过程中遇到的常见问题,我们做了一个整理总结,并给出了解决问题的步骤或方案,大家可以按照指定的步骤发现和解决问题。
一. 公共异常
1.程序运行过程中,抛出 OutOfMemoryException (内存不足)。
此时往往意味着存在内存泄露或内存占用太大。此问题常见的原因有:内存中有堆积的排队要处理的任务太多,或在内存中保存很多大的位图和文件,不再使用的内存空间没有释放等等。
2.System.Drawing.Graphics.GetHdc()抛出“参数无效”。
这个问题就是上述“内存不足”的另一个表现形式。参考上述说明处理。
二. MFile 相关:
1.启动报错:无法加载DLL "OMFile.dll",或“调用目标发生了异常”。
(01)确保在运行目录下存在所需的所有非托管dll,可以解压MFile的SDK压缩包获取。
(02)缺少VC++运行时,点击下载安装即可(压缩包中的三个文件都需要安装)。
2.初始化异常:OMFile initialize error.
如果在调用VideoFileMaker / SilenceVideoFileMaker / AudioFileMaker 的Initialize方法时,抛出上述异常,则可做如下检查:
(01)文件的保存路径是否包含非法字符?各级目录文件夹是否存在?
(02)当前运行程序对录制文件的保存路径是否有写权限?比如win7系统,C盘中除“我的文档”目录外,普通程序是没有写权限的,除非"以管理员身份运行"。
(03)Initialize方法的其它各个参数的值是否正确有效?
3.初始化异常:The value of videoWidth and videoHeight must be devided by 4.
MFile要求录制的视频帧的长和宽必须是4的整数倍。如果您视频帧尺寸不符合要求,请先对视频帧进行裁剪。
可使用ESBasic.dll类库中 ESBasic.Helpers.ImageHelper 提供的RoundSizeByNumber静态方法对图像进行裁剪。
4.MFile结合OMCS对摄像头视频和桌面视频进行录制时,出现问题?
由于OMCS的视频编解码算法要求宽和高必须是8的整数倍,所以,OMCS内部会自动将视频图像修正为8的整数倍,这也意味着OMCS的摄像头和远程桌面连接器的GetCurrentImage方法返回的图像的宽和高也是经过修正的。因此,在调用MFile的Initialize方法时,要注意在传入videoWidth和videoHeight之前,先将它们修正一下,如:int newWidth = width / 8 * 8 ;
5.录制生成的文件播放不了.
(01)调试程序,在调用AddVideoFrame 和 AddAudioFrame方法的地方加断点,看其是否被调用。
(02)确保AddVideoFrame 和 AddAudioFrame方法的参数(视频帧、音频帧)的帧信息与Initialize方法指定的完全一致(比如,视频帧的高和宽,音频的采样率、声道数等)。
(03)录制结束时,调用的Close方法(WaitFinished参数必须传入true)成功返回了吗?只有Close方法成功返回,才表示录制是成功的。
6.执行VideoFileMaker / SilenceVideoFileMaker / AudioFileMaker 的Close方法(WaitFinished参数为true)时,好像卡住了一样?
首先,如果MFile录制的是OMCS的摄像头视频或桌面,请首先确保第3点问题已经解决。
MFile采用的后台录制模式,当您调用AddVideoFrame 和 AddAudioFrame方法时,MFile会将传入的视频帧/音频帧放入到队列中,另一个后台线程会从队列中按顺序取出帧来处理。所以,如果采集的速度大于处理的速度,那么录制一段时间后,队列中将会存在许多待处理的帧(可以通过VideoFileMaker的ToBeProcessedVideoFrameCount属性得到待处理视频帧的个数),只有等后台线程将队列中的所有帧取出处理后,Close方法才会返回。
遇到这种情况可以采取如下办法:根据运行录制程序的电脑的性能高低来决定视频帧采集的频率高低,从而让采集的速度与处理的速度基本一致,这样,Close方法就能迅速返回了。
7.播放录制生成的mp4文件时,帧频低于设置的值?
(1)对于录制摄像头而言,主要因素一般在于摄像头。 摄像头标定的最大帧频(可使用设备测试程序来读取该信息),指的是峰值;而录制生成的文件的帧频,指的是均值。
而且,摄像头实际能达到的采集帧频与画面的明暗和变化程度都有关。因此,要想达到理想的帧频,需要将摄像头的采集帧频设置成更大。
比如我们的测试报告:室内光线亮度一般,画面变化较大,将摄像头帧频选定在60时,录制的视频文件达到的帧频是38。
(2)对于录制桌面而言,主要制约因素是是CPU。录制桌面的Size越大、帧频越高,对CPU的消耗也就越大。如果CPU性能不够,则会制约录制视频所能达到的最大帧频。
此外,也可能会造成录制文件的音、视频不同步的现象。您可以在录制的时候,通过任务管理器来查看CPU的消耗情况。
8.录制生成的视频文件,其时间长度小于录制的时间?
首先,不要在Close方法返回后,就立即播放生成的mp4文件,因为可能此时内存中的数据还尚未完全写入到mp4文件中。等10~20秒后,再打开mp4文件播放。
如果是仅仅录制视频图像(没有声音),那么录制生成的视频文件在播放时是严格按照MFile的Initialize方法传入的fps帧频参数来的。这种情况下,如果采集的帧频不稳定(比如像上面问题8中所说的那样,摄像头的采集帧频达不到标称值),那么就会出现录制了40秒,播放却只有38秒左右的情况。
9.录制过程中发现内存占用较高,是内存泄漏吗?
不是内存泄漏。这种情况一般这样造成的:
如果CPU性能较低,造成了采集得到的图像帧未能及时的编码处理,这样队列中待处理的帧就越来越多,从而导致内存升高。
队列中待处理的帧的个数可通过VideoFileMaker的ToBeProcessedVideoFrameCount属性来查看。
可以用一个定时器,每秒刷新一次,在UI上将这个值显示出来,如此就可以在录制过程中实时观察堆积的情况。
如果确定有排队堆积的情况,通常,在录制一段时间后,就会抛出OutOfMemoryException异常而导致录制中断。
解决的方法有:提高CPU的主频、降低帧频、降低分辨率。
另外,还有一种方法:主动丢弃视频帧以适应电脑处理能力不够的情形:每次AddVideoFrame之前,先判断一下待处理帧数,如果大于4,就扔掉当前帧。
如下代码所示:
void Form1_ImageCaptured(Bitmap img) { if (this.videoFileMaker.ToBeProcessedVideoFrameCount < 4) { this.videoFileMaker.AddVideoFrame(img); } }
这个方法会自动调整适配到与当前电脑处理能力相应的帧频,同时也避免了视频帧在队列中不断堆积最终导致内存溢出的异常。
10.录制了很长时间,结果生成的视频文件的长度最多只有5分钟左右?
这是试用版的MFile的限制。试用版MFile有三个限制:(1)过期日期限制;(2)自程序启动开始计时,最多只能运行10分钟;(3)最多只能录制5分钟。
11. AddVideoFrame 方法抛出异常:The size of frame is wrong .
(1)检查Initialize中设置的videoWidth、videoHeight的值,与AddVideoFrame(Bitmap frame)方法的参数图片的Size是否相符。
(2)若相符,而偶发该异常,则可能是AddVideoFrame的时候,录制器FileMaker还没有初始化完成,应确保在初始化方法返回后,再调用AddVideoFrame。
12. 停止视频录制时,报错:生成视频文件失败!尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
这种情况通常是因为在整个录制过程中没有加入任何有效的视频帧。可能原因是:
(1)AddVideoFrame 方法没有被调用过。
(2)传入AddVideoFrame 方法的参数无效,为null。
三. MCapture 相关:
1.CameraCapturer:目标摄像头不支持指定的分辨率!
(01)首先查看在运行的机器上参数cameraIndex索引指定的摄像头是否存在?
(02)使用OMCS设备测试程序测试一下目标摄像头所支持的分辨率,然后选择一个正确的分辨率传给CapturerFactory的CreateCameraCapturer方法。
2.采集一段时间后,就黑屏了(或者没有图像/声音输出了)!
这是试用版MCapture的限制。试用版MCapture有两个限制:(1)过期日期限制;(2)自程序启动开始计时,最多只能运行10分钟。
3. IDesktopCapturer 触发 CaptureError 事件,异常信息为“参数无效”。
由于桌面采集得到的每张图片所占用的内存都很大(一张可能就有好几M) ,当内存中缓存了很多屏幕图片时,就会出现OutOfMemoryException,在这种情况下,采集桌面的方法就会抛出“参数无效”的异常,方法名称为“ System.Drawing.Graphics.CopyFromScreen”。更具体的说明可以参见本FAQ的第一个问答。
4.CapturerFactory 的 CreateAudioMixter 方法抛异常:Current soundcardCapturer is not supported by AudioMixter。
这是由于声卡的采样率不是48000导致的,此时,可以按下图设置一下扬声器的属性:
5. 如何为图片增加水印?
免费版的MCapture采集到的图片,是带有水印的“Free version from www.oraycn.com”,下面是为图片加上这个水印的代码,供大家参考:
6. 是否可以同时采集多个摄像头?
可以的,只要调用CreateCameraCapture方法创建多个采集器实例并启动采集,即可同时采集多个摄像头。
注意:多个摄像头不要同时启动(ICameraCapturer的Start方法),中间最好间隔100毫秒,否则,后面的摄像头可能会启动失败。
7. 是否可以采集屏幕的指定区域?
可以的,CapturerFactory 的 CreateDesktopCapturer方法有个重载,接受一个Rectangle类型参数,可以通过该参数来指定要采集的矩形区域。 (即区域采集、区域录制)
四. StriveEngine 相关:
1. 如何让 StriveEngine 同时支持带 SSL 的 WebSocket ?
(1)现已部署的基于 StriveEngine 的服务端程序(A服务)不需要做任何修改。
(2)添加一个支持 SSL 的 Nginx Server 作为代理(B服务),配置该服务器,将请求转发到上述的真正的A服务的端口上。(如何配置Nginx服务器,可参见这里。)
(3)如果一个客户端是普通的WebSocket,则还是直接连A服务;如果一个客户端是带SSL的WebSocket,则连接B服务。
2. 发送数据接收不到?
需要检查消息协议,必要时可将消息结束符设置为 null 进行测试:new DefaultTextContractHelper(null)。
五. OAUS 相关:
1. 升级失败,客户端提示:网络中断,升级失败,请稍后再试!
(1)检查网络连接,看是否正常。
(2)查看OAUS服务端运行目录下是否有 ESFrameworkLog.txt 日志文件,如果有,打开看其中日志记录。
如果记录中含有如下内容“Size of message to be post overflow! ”,则需要将允许的最大消息尺寸设置大一些。
在Rapid引擎初始化之前调用GlobalUtil的SetMaxLengthOfMessage方法设置消息的最大长度,客户端与服务端均须设置,且要设置成一致。
public static void SetMaxLengthOfMessage(int maxLen);
该方法详细说明请参见这里。
(3)查看OAUS客户端目录下的UpdateLog.txt日志文件,其中是否有类似“xxx文件被占用”的信息,如果有,表示要升级的客户端程序仍然还在运行中,没有完全退出。
将客户端进程完全退出后,再重新运行OAUS客户端进行升级即可。
上一篇:傲瑞组件 开发手册与使用技巧
----------------------------------------------------------------------------------------------------------------------------
阅读 更多OMCS开发手册系列文章。
Q Q:168757008