转载请注明: TheViper http://www.cnblogs.com/TheViper 

原来发表过一篇分段播放的flash播放器。这个播放器其实就没有神马原理,就是把一个视频分成好几个视频,点播的时候通过关键帧(keyframe)索引找到离点击点最近的关键帧播放。如果当前快要播放完,就去加载下一段。当前播放完,就播放下一段。

原理很简单,实现起来却很是纠结,痛苦。因为本质上是一开始就创建了几个video,播放,点击,缓冲等时候就需要不停的计算下一个要播放的第几个video,然后像放幻灯片那样切换,虽然不明显。然后计算的时候兼容flv和mp4也很无语,就像搞浏览器兼容一样。另外,点播的时候会多一次请求,用于获取关键帧信息。如果这个关键帧信息很大很长的话,体验是非常不好的。

这么多不足,就尝试下另一种方案hls.

hls m3u8的优点在于不错的兼容性。

可以看到m3u8通杀移动设备,而不支持的设备都是浏览器,可以通过flash播放器解决。事实上现在有长视频的视频网站在pc端基本上都用的m3u8.短视频的话用视频伪流技术(pseudo streaming)就已经可以满足要求了。

具体怎么写呢?通常都是用的osmf和HLSProvider,比如百度云网盘里面的播放器,

HLSProvider(org.denivip.osmf包)已经封装好了一切,com.baidu.player.DiskPlayer里面是很简单的调用。

然而我却发现了更好的东西flashls。 这个东西好在体积小,它例子里的flashlsChromeless.swf只有36kb.刚开始我不敢相信,因为那些视频网站的swf(皮肤swf除外)都是150kb以上,这让我觉得好像写一个flash hls写完真的就要好几百kb,另外,它没有其他依赖,比如加密类,osmf....

事实上,真正对hls m3u8的解析要不了那么多.

这类hls plugin通常都被当做那些开源播放器(flowplayer,osmf,jwplayer)的hls插件,用以支持hls.比如上面的HLSProvider就只支持OSMF 2.0 based video players,而osmf即使是只有最基本的功能,也有100多kb,再加上hurlant加密包,就更大了。

效果

下面开始进入正题,看看hls player是怎么做的。

1.进入flashls文件下src文件夹,取出org包,放到项目文件夹。将里面每个文件形如CONFIG::LOGGING{}的代码去除,因为没有flex builder环境,flash无法编译。这个是去除后的flashls

2.调用flashls封装,具体的可以看flashls examle目录下chromeless的那个例子,很详细。

hls事件

        private function _init_events()
{
stage.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);
}
private function _onStageVideoState(event : StageVideoAvailabilityEvent):void
{
var available : Boolean = (event.availability == StageVideoAvailability.AVAILABLE);
_hls = new HLS();
HLSSettings.maxBufferLength = 10;//最大缓存长度
HLSSettings.seekMode = "ACCURATE";//查找模式
_hls.stage = stage;
_hls.addEventListener(HLSEvent.MANIFEST_LOADED, _manifestHandler);
_hls.addEventListener(HLSEvent.MEDIA_TIME, _mediaTimeHandler);//当前播放回调
_hls.addEventListener(HLSEvent.FRAGMENT_PLAYING, _fragmentPlayingHandler);//片段播放回调
_hls.addEventListener(HLSEvent.PLAYBACK_STATE, _stateHandler);//当前状态回调
if (available && stage.stageVideos.length > 0)
{
_stageVideo = stage.stageVideos[0];
_stageVideo.attachNetStream(_hls.stream);
}
else
{
_video = new Video();
addChild(_video);
_video.smoothing = true;
_video.attachNetStream(_hls.stream);
}
stage.removeEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, _onStageVideoState);
}

两个设置需要注意

maxBufferLength表示最大的缓冲长度,比如我的片段是10秒一个,maxBufferLength设置成20秒,那么当我播放的时候,播放器会加载后两个片段,如果暂停了,那播放器缓冲完后两个片段就不再加载片段了。这个做的真的很赞,既保证了用户体验,又节约了流量,另外如果在m3u8文件中配置了多码率的话,会根据用户当前的网速,匹配相应清晰度的片段。

seekMode可以为ACCURATE,KEYFRAME,SEGMENT。

ACCURATE表示点播时会精确的跳到点播位置,这个乍看之下很好,实际用时会发现如果片段稍微长一点,画面会从点播的片段开头快进到点播位置。

KEYFRAME表示定位基于关键帧,这个也有问题,那就是一般的关键帧是几秒一个,这样点播的时候会有几秒的误差,因为只能用关键帧定位。

SEGMENT表示点播时会跳到包含点播位置的片段的开头。在直播的时候可以用这个。

然后是回调

        private function _manifestHandler(event : HLSEvent):void
{
_duration = event.levels[_hls.startlevel].duration;
if (_autoLoad)
{
_play(-1);
}
}
private function _mediaTimeHandler(event : HLSEvent):void
{
_duration = event.mediatime.duration;
_media_position = event.mediatime.position;
nav.progress_line.x = _media_position / _duration * W;
nav.progressBar.width = (_media_position + event.mediatime.buffer) / _duration * W;
nav.notify.text = formatTime(_media_position) + " / " + formatTime(_duration);
}
private function _fragmentPlayingHandler(event : HLSEvent):void
{
_video.width = _videoWidth = event.playMetrics.video_width;
_video.height = _videoHeight = event.playMetrics.video_height;
_video.x=(stage.stageWidth-_video.width)*0.5;
_video.y=(stage.stageHeight-_video.height)*0.5;
}
private function _stateHandler(event : HLSEvent):void
{
if (event.state == 'PLAYING_BUFFERING')
{
buffering.visible = true;
}
else
{
buffering.visible = false;
}
}

_manifestHandler里面可以得到视频的总长度,注意这里不是片段长度。

_mediaTimeHandler也可以得到视频总长度,还有视频播放的当前位置,当前缓冲长度。因此里面可以更新播放条,缓冲条长度,和播放时间。

_stateHandler可以得到播放器视频流当前的状态,比如停止,暂停,缓冲,播放等状态。

_fragmentPlayingHandler里面可以获取视频信息,比如宽度,高度

最后是hls对netstream封装的方法

        private function _load(url : String):void
{
_hls.load(url);
}
private function _play(position : Number = -1):void
{
_hls.stream.play(null, position);
}
private function _pause():void
{
_hls.stream.pause();
}
protected function _resume():void//回放
{
_hls.stream.resume();
}
private function _seek(position : Number):void
{
_hls.stream.seek(position);
}
private function _stop():void
{
_hls.stream.close();
}
private function _setVolume(percent : Number):void
{
st.volume = percent / 100;
_hls.stream.soundTransform = st;
}
private function _getVolume():Number
{
return _hls.stream.soundTransform.volume;
}

里面需要注意的_load方法,传入的是m3u8文件地址,不是视频地址。播放器会自动解析m3u8文件,加载相应视频片段。

3.视频分段,并生成m3u8文件

可以看这一篇文章.

需要注意的是这里的音频编码是aac,是ffmpeg实验的东西,需要加上后面的-strict -2才不会报错。另外,-hls_list_size参数取的稍微大点,因为它表示写入m3u8文件的片段信息个数,比如取值为3,那只有3个片段信息被写入m3u8。

默认得到的片段格式是ts,这个格式不像mp4,flv,f4v.ts是独立编码,不依赖头信息的,在点播的时候不像前面说的那些格式,需要加载头信息,获取关键帧列表后,才能根据关键帧跳到点播位置。

最后说下怎么使用这个播放器

        flash_object.embedSWF('http://localhost/hls_example/youku_player.swf','wrap_player','youku_player','720','540',{
url:'http://localhost/hls_example/videos/video.m3u8'
},{wmode:'transparent'});

想播放器传入url参数,值为m3u8地址就可以使用了。

hls_example

播放器源码

只有44kb!

 

小巧的http live streaming m3u8播放器的更多相关文章

  1. 分段播放的flash播放器

    效果: 视频分段好处显而易见,就是节省流量,因为看视频很多时候都不会看完,还有很多时候是跳着看的.还有的时候也许用户暂停视频出去买东西了... 本文不讨论flash rtmp直播流,例子用的是普通的h ...

  2. m3u8的浏览器播放器

    前几天花了点时间研究了下怎么在浏览器中播放m3u8的视频地址,最后终于找到了两个开源的东西可以正常播放,稍稍整理下方便后来人. m3u8是什么就不介绍了,现在所有视频网站基本都是通过m3u8的方式来播 ...

  3. 推荐下:开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !

    视频播放, 原本是想h5 自带视频播放,使用很简单,结果现实很骨感. <video controls="controls" preload="auto" ...

  4. (转载)开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !

    文章链接:http://justcoding.iteye.com/blog/2110275 CKplayer,其全称为超酷flv播放器,它是一款用于网页上播放视频的软件,支持的格式有:http协议上的 ...

  5. 最简单的基于Flash的流媒体示例:网页播放器(HTTP,RTMP,HLS)

    http://blog.csdn.net/leixiaohua1020/article/details/43936415 ======================================= ...

  6. 使用Vitamio打造自己的Android万能播放器(1)——准备

    前言 虽然Android已经内置了VideoView组件和MediaPlayer类来支持开发视频播放器,但支持格式.性能等各方面都十分有限,这里与大家一起利用免费的Vitamio来打造属于自己的And ...

  7. Android之万能播放器解码框架Vitamio的介绍及使用

    一.简介 Vitamio能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在Android 与 iOS 上跨平台支持 MMS, RTSP, R ...

  8. Android播放器推荐:可以播放本地音乐、视频、在线播放音乐、视频、网络收音机等

    下载链接:http://www.eoeandroid.com/forum.php?mod=attachment&aid=MTAxNTczfGMyNjNkMzFlfDEzNzY1MzkwNTR8 ...

  9. EasyPlayer.js网页全终端播放器安装使用文档

    EasyPlayer.js 集 rtmp, hls, flv, websocket 于一身的网页直播/点播播放器, 使用简单, 功能强大 属性(Property) video-url 视频流地址 St ...

随机推荐

  1. Python基础教程【读书笔记】 - 2016/8/3

    希望通过博客园持续的更新,分享和记录Python基础知识到高级应用的点点滴滴! 第十一波:第11章  文件和素材 本章更进一步,让程序能够接触更多的领域:文件和流.接下来介绍的函数和对象可以让你在程序 ...

  2. Nginx做反向代理总是被系统kill

    公司使用Nginx做反向代理,以前都挺正常的,最近不知怎么回事总是无端被系统kill,而在nginx错误日志中也没有信息输出. 网上查了很多资料,也没什么靠谱的回答,唯一觉得有点关联的就是linux ...

  3. linux awk命令

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...

  4. linux svn迁移备份的三种方法

    原文:http://www.iitshare.com/linux-svn-migration.html svn备份方式对比分析 一般采用三种方式: 1.svnadmin dump 2.svnadmin ...

  5. 黄聪:mysql下使用update set from select

    UPDATE friends INNER JOIN users ON friends.friendid=users.userid SET friends.friendname=users.userna ...

  6. javascript 异步编程-setTimeout

    javascript的执行引擎是单线程的,正常情况下是同步编程的模式,即是程序按照代码的顺序从上到下依次顺序执行.只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行.常见的浏览器无 ...

  7. android 通知

    https://developer.android.com/design/patterns/notifications.html 通知系统可让用户随时了解应用中的相关和即时事件,例如来自好友的新聊天信 ...

  8. vs2012出现无法启动iis express web 服务器的错误

    一直用的好好的,今天调试时却总报上面的错误.“文件查看器”->"windows 日志"->"系统"里发现有几条“HttpEvent”错误, 具体信息 ...

  9. jquery ready 延迟

    $.holdReady(true);//延迟 $.holdReady(false);//解延迟 用于下载文件的时候,异步操作 $.holdReady(true); $.getScript(" ...

  10. mac eclipse 下安装subclipse

    参考 http://www.cnblogs.com/yinxiangpei/articles/3859057.html 推荐安装homebrew 在安装javahl时注意版本对应 http://sub ...