• 解决ActionScript对FMS视频拍照的安全沙箱2123问题


    最近在做一个在线视频的网站,采用了FMS+ASP的架构,FMS负责视频流的广播,ASP页面通过加载一个播放器jwplayer实现对FMS所广播视频流的播放,这也是很多的视频网站采用模式,不再赘述,只表扬一下jwplayer播放器,相当的好用! 

    网站有一个功能,需要在用户端实现对当前播放视频的截图,而客户又不允许使用类似QQ截图似的那种插件,要求通过flash播放器来实现,无奈,只好往深里去探究一下播放器了。 

    通过一顿阅读源代码和查找相关资料,确定了通过给我们的jwplayer播放器写插件的方式来实现这个功能(其实这个插件还实现了好多其他功能:比如双击全屏、自动跳过预先设置的某几个时间段等)的方式,写jwplayer插件的相关知识可以在网上找到,也不再多说。 

    进入正题:jwplayer使用的是flash的ActionScript语言,通过阅读相关API,发现了可以使用BitmapData类的draw方法来实现截图,然后通过JpegEncoder类来进行编码即可生成jpg图片数据,但flash存在一个安全问题,即通过这种方法在客户端生成的图片数据,是不能通过FileReference的save方法直接保存在用户本地的(又是flash的安全设置,蛋疼),需要将这些数据发送到后台,由后台来生成图片,如果用户需要使用这些图片的话,还需要想办法让用户进行下载。 

    截图功能相关代码:

    1.引入包:

    import com.adobe.images.JPGEncoder;//jpg编码类

    import flash.display.*;//BitmapData类

    2.截图

    private var bitmap:BitmapData;

    private var encoder:JPGEncoder;

     

    bitmap = new BitmapData(width, height,false,0x000000);

    var req:URLRequest = new URLRequest('http://localhost:41921/Util/Clip');//处理图片数据的ASP控制器

    req.method = URLRequestMethod.POST;

    try{

      bitmap.draw(videoObject());//截图

      req.requestHeaders.push(new URLRequestHeader("Content-type","application/octet-stream"));

      req.data = encoder.encode(bitmap);

            loader.load(req); 

    }catch(err:SecurityError)

    {}

     

    代码中的loader用于向后台以流的形式发送图片数据,后台的保存方法如下:

    相关包:

    using System.IO;

    using System.Drawing.Imaging;

     

    保存图片代码:

    public void Clip()

            {

                int length = Request.TotalBytes;

                byte[] values = new byte[length];

                values = Request.BinaryRead(length);

     

                string imageName = "/Resources/Images/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".jpg";

     

                FileStream fs = new FileStream(Server.MapPath(imageName), FileMode.Create, FileAccess.Write);

                BinaryWriter bw = new BinaryWriter(fs);

                bw.Write(values);

                bw.Close();

                fs.Close();

            }

     

    如果一切都能顺利运行的话,就不用写这篇文章了,在 bitmap.draw(videoObject()); 这句运行的时候往往会产生“安全沙箱Error #2123错误”,这个错误说明出现了安全沙箱问题,相关说明:

    如果BitmapData的draw方法的对象和其所有子对象(如果是 Sprite 或 MovieClip 对象)与调用方不来自同一个域,或者不在调用方可通过调用 Security.allowDomain() 方法访问的内容中,则调用 draw() 将引发 SecurityError 异常。 

    这说明所draw的视频对象和当前调用draw方法的这个swf(即jwplayer)不在同一个域内,所以出现了安全沙箱问题。因为jwplayer播放器所播放的视频来自FMS的rtmp流,而jwplayer及其所加载的插件(swf文件)在用户本地,可不是不在一个域内吗?找了下网上的资料,好多人都遇到了这个问题,却没有解决的办法,这里提出一个可行的办法:

     

    通过查找FMS、ActionScript的相关资料,发现“对于BitmapData的draw方法,在 Flash Player 9.0.115.0 及更高版本和 Adobe AIR 中,通过 RTMP 支持此方法。在 Flash Media Server 上,可以在服务器端脚本中控制对流的访问。…通过设置Client.audioSampleAccess 和 Client.videoSampleAccess 属性(,可以赋予用户端操作视频流的权限)。”

     

    理论总是让人不容易理解,结合本人的例子来说明:

    我的网站中,客户端所播放的视频来源都是FMS中的某一个application,比如:直播的话视频源为:rtmp://localhost:1935/live  点播的话视频源为:rtmp://localhost:1935/vod  其中的live和vod就是FMS服务器中的application,即用于提供某种视频服务的FMS服务器端ActionScript程序。

    当用户在打开视频的时候,播放器会根据视频的源(比如:rtmp://localhost: 1935/vod/a.flv)中的vod去连接FMS服务端的vod应用(位于 “FMS安装路径/ applications”文件夹下,相应的还有live应用),然后连接vod应用,并向其请求播放某个视频流,vod应用处理用户的连接请求和视频播放请求,并将相应的视频流推给客户端。

    我们要做的,就是在vod应用的onConnect处理方法中,为客户端赋予操作视频流的权限,正常来说,类似vod这种应用的文件夹下会有一个main.as文件(服务器端ActionScript程序),这个文件可以进行编辑,但有时候也会是一个main.far文件,这个就不好编辑了,没关系,在 FMS安装路径下,找到“samples\applications\vod”文件夹,将其中的main.asc文件复制到 FMS安装路径下的 “applications\vod”文件夹下,然后删除main.far文件,打开这个main.asc文件,找到其中的application.onConnect方法,然后找到

    //p_client.audioSampleAccess = "/";

    //p_client.videoSampleAccess = "/";

    两句代码,它们上边应该还有注释说明…  哈,其实FMS开发人员早就给我们考虑到这个功能了,只不过给注释掉了,好了,现在取消这两句的注释:

    即改为:

    p_client.audioSampleAccess = "/";

    p_client.videoSampleAccess = "/";

    然后重启FMS服务,再次在客户端使用截图功能,好了!

    客户端提示:

     

    截好并保存在服务器端的图片:

     

     

    注:本文所述方法只在基于FMS的rtmp视频流中应用成功,对于不使用FMS,播放本地视频的应用场景没有进行测试,但貌似那种方式不会存在安全沙箱问题,如有朋友需要进一步讨论,可以加QQ:563084310

     

  • 相关阅读:
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行 已解决!
    iis 无法在Web服务器上启动调试。打开的URL的IIS辅助进程当前没有运行
    aspx页面,Page_Load 无人进入,解决
    Ajax后台传数组参数,接收不到报错!
    FusionCharts和highcharts 饼图区别!
    redis
    Hibernate不同数据库的连接及SQL方言
    Kafka
    Zookeeper
    BaseDao+万能方法 , HibernateDaoSupport
  • 原文地址:https://www.cnblogs.com/xiaoSoldier/p/2846044.html
Copyright © 2020-2023  润新知