子曾经曰过

  博客园  :: 首页  ::  ::  ::  :: 管理

经过一些对JW和FLOW播放器的研究,最后还是用OSMF写了一个简单的播放器,估计最好还是用FLASH自身的控件写更好控制一些,毕竟程序员最好能对底层比较了解,这样对播放器的修改时非常有好处的。

下面有些凌乱的注意点:

1:跨域问题 

比如我在本地要播放一个网站 www.test.com下面的FLV流文件,那么FALSH9.0之前系统会以http方式去请求是否有这样一个文件

crossdomain.xml文件存在,这个文件是把钥匙,你要访问我服务器上的东西,就得有这个钥匙,钥匙的一般写法是 

<!-- http://www.adobe.com/crossdomain.xml -->
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>  意思是允许所有的域来请求服务,进行操作。
如果只允许某些进行访问,请GOOGLE.
 
2:参数传递问题
这个问题一开始也困扰了我很久

<script type='text/javascript'>
var so = new SWFObject('OsmfPlayer.swf','ply','480','400','9','#000000');
so.addParam('allowfullscreen','true');
so.addParam('allowscriptaccess','always');
so.addVariable('PlayUrl', 'http://www.test.com?a=1&b=2);
so.write('flashcontent');
</script>

注意啊,上面的addParam和addVariable很容易混淆,实际上我个人认为吧,前者是flash自带的参数名,如allowfullscreen是不能更改的,后者是自定义的变量,名字可以更改。

这边就涉及到一个新的问题。PlayUrl这个参数后面的值是一个带?和&的字符串,如何在AS3里完整获得这个字符串值也是一个麻烦事,目前个人写法是进行拼接。写成这样:

so.addVariable('PlayUrl', 'http://www.test.com');

so.addVariable('a', '1');

so.addVariable('b', '2');

然后在AS3里用this.loaderInfo.parameters.PlayUrl,this.loaderInfo.parameters.a,this.loaderInfo.parameters.b获得各自的值进行拼接赋给播放器。

挺麻烦,不知道有没有更好的办法?

3:元数据的获得

element.client.addHandler("onMetaData", onMetaData);  //添加侦听

private function onMetaData(info:Object):void
{
metadata_ = info;
print("获取元数据");
print("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
/*var m:Number;
//print(info.seekpoints); //只对mp4有效
for (m=0; m<info.seekpoints.length; m++) {
print(info.seekpoints[m]["time"]); //枚举最重要
}

var n:Number; //keyframes 只对flv有效
for (n=0; n<info.keyframes.filepositions.length; n++) {
print(' fileposition: '+info.keyframes.filepositions[n]+' time: '+info.keyframes.times[n]); //枚举最重要
} */
}

元数据获得分为FLV和MP4,FLV和MP4的拉动都是通过关键帧来实现的,但是差别还是挺大的:

mp4文件的SEEK点叫做metadata.seekpoints,flv的叫做keyframes,这个差别是很大的。

private function onMetaData(info:Object):void
{
true_duration = player.duration;

(controlbarlayout.getChildByName('totalshowtext') as TextField).setTextFormat(format1);
(controlbarlayout.getChildByName('totalshowtext') as TextField).text = timeFormat(player.duration);

metadata_ = info;
var m:Number;
//print(info.seekpoints); //只对mp4有效
for (m=0; m<info.seekpoints.length; m++) {
print(info.seekpoints[m]["time"]); //枚举最重要
}

print("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);

var n:Number; //keyframes 只对flv有效
for (n=0; n<info.keyframes.filepositions.length; n++) {
print(' fileposition: '+info.keyframes.filepositions[n]+' time: '+info.keyframes.times[n]); //枚举最重要
}
}


mp4寻找SEEK点方法

private function get_nearest_seekpoint(second:Number, seekpoints)
{
var index1 = 0;
var index2 = 0;
// Iterate through array to find keyframes before and after scrubber second
for(var i = 0; i != seekpoints.length; i++)
{
if(seekpoints[i]["time"] < second)
{
index1 = i;
}
else
{
index2 = i;
break;
}
}
// Calculate nearest keyframe
if(second - seekpoints[index1]["time"] < seekpoints[index2]["time"] - second)
{
return index1;
}
else
{
return index2;
}
}

调用

var keyframe = get_nearest_seekpoint(dragsecond, metadata_.seekpoints);  //元数据应该是第一次所取得的元数据,而且metadata_.seekpoints矩阵值应该保持不变
print("seek: nearest keyframe=" + keyframe);
var playsecond:Number; //附近关键帧的有效开始时间点
playsecond = metadata_.seekpoints[keyframe]["time"];
print("seek second" + playsecond);
print("seek操作后播放地址是:"+videoUrl+"?start="+playsecond);
element.resource = new URLResource(videoUrl+"?start="+playsecond);
player.media = element;

 

一个播放器如果不能正确播放给定的FLV或MP4文件,需要几个方面检查:

1:Fiddler抓到的播放实际路径是不是和给定路径一模一样,有时候参数有一点错误也是不能播放的。

2: 搞清楚是否有跨域问题存在。

3:播放器SWF帧率是不是和视频帧率一致,据说这个有影响。


posted on 2012-02-15 17:39  人的本质是什么?  阅读(788)  评论(0编辑  收藏  举报