標籤:flash actionscript 播放 推流 rtmp
本文記錄一些基於Flash的流ApsaraVideo for Media Processing的例子。Flash平台最常見的流媒體協議是RTMP。此前記錄的一些基於C/C++的RTMP播放器/推流器,但是沒有記錄過基於Flash中的ActionScript的RTMP播放器/推流器。其實基於Flash的RTMP播放器/推流器才能算得上是RTMP技術中的“正規軍”。RTMP本身設計出來就是用於Flash平台之間通訊的,而且RTMP最大的優勢——“無外掛程式直播”,也是得益於廣泛安裝在用戶端的Flash Player。因此本文分別記錄一個基於ActionScript的RTMP播放器和基於ActionScript的RTMP推流器。
基於C/C++的RTMP流ApsaraVideo for Media Processing的例子可以參考下面幾個。
發布
最簡單的基於librtmp的樣本:發布H.264(H.264通過RTMP發布)
最簡單的基於librtmp的樣本:發布(FLV通過RTMP發布)
最簡單的基於FFmpeg的推流器(以推送RTMP為例)
接收
最簡單的基於librtmp的樣本:接收(RTMP儲存為FLV)
最簡單的基於FFMPEG+SDL的視頻播放器 ver2 (採用SDL2.0)
簡介
相比於使用C/C++處理RTMP而言,使用ActionScript處理RTMP非常的簡單。RTMP建立串連的方法都已經封裝好了,只需要調用現成的介面函數就可以了。但是使用ActionScript處理RTMP的劣勢也十分明顯——可供自己開發的地方很少。由於Flash本身不開源,所以我們無法得到它的底層代碼,因而也不能對編解碼底層的參數進行調整。總而言之,ActionScript處理RTMP可以概括為幾個字:“簡單但是不靈活”。
ActionScript播放RTMP
ActionScript播放RTMP流媒體的流程如所示。
可以看出,流程可以分成兩部分:播放和顯示。
播放
播放分成3步:
(1)建立NetConnection
(2)建立NetStream
(3)調用NetStream的play()方法
前2步分別建立了RTMP規範中的兩個邏輯結構:NetConnection和NetStream。NetConnection代表格服務器端應用程式和用戶端之間基礎的連通關係。NetStream代表了發送多媒體資料的通道。伺服器和用戶端之間只能建立一個NetConnection,但是基於該串連可以建立很多NetStream。這兩個結構的結構如所示。
顯示
顯示部分將播放的視頻顯示在“舞台”上。這一部分通過建立一個Video對象實現。
ActionScript推送RTMP
ActionScript推送RTMP流媒體的流程如所示。
可以看出,推送RTMP的流程和播放有些類似,最主要的不同在於推送最後調用的是NetStream的publish()方法,而播放最後調用的是NetStream的play()方法。推流分成4步:
(1)建立NetConnection
(2)建立NetStream
(3)綁定網路攝影機和麥克風
(4)調用NetStream的play()方法
推流程式開始運行後,可以通過ffplay,VLC或者Flash應用程式訪問相應的RTMP URL查看流媒體。
代碼
本文附件中包含以下2個ActionScript工程:
simplest as3 rtmp player,最簡單的RTMP播放器,其中包含3個獨立的子工程:
simplest_as3_rtmp_player:最簡單的RTMP播放器。
simplest_as3_local_player:最簡單的本地檔案播放器。
simplest_as3_rtmp_player_multiscreen:最簡單的RTMP多屏播放器。
simplest_as3_rtmp_streamer,最簡單的RTMP推流器
下面看一下上述幾個工程的原始碼。
simplest_as3_rtmp_player
simplest_as3_rtmp_player是最簡單的RTMP播放器,代碼如下所示。
/** * 最簡單的基於ActionScript的RTMP播放器 * Simplest AS3 RTMP Player * * 雷霄驊 Lei Xiaohua * [email protected] * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程式使用ActionScript3語言完成,播放RTMP伺服器上的流媒體 * 是最簡單的基於ActionScript3的播放器。 * * This software is written in Actionscript3, it plays stream * on RTMP server * It‘s the simplest RTMP player based on ActionScript3. * */package { import flash.display.Sprite; import flash.net.NetConnection; import flash.events.NetStatusEvent; import flash.events.AsyncErrorEvent; import flash.net.NetStream; import flash.media.Video; public class simplest_as3_rtmp_player extends Sprite { var nc:NetConnection; var ns:NetStream;var video:Video; public function simplest_as3_rtmp_player() { nc = new NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);nc.connect("rtmp://localhost/live"); } private function netStatusHandler(event:NetStatusEvent):void {trace("event.info.level: " + event.info.level + "\n", "event.info.code: " + event.info.code); switch (event.info.code) { case "NetConnection.Connect.Success": doVideo(nc); break;case "NetConnection.Connect.Failed":break; case "NetConnection.Connect.Rejected":break; case "NetStream.Play.Stop":break; case "NetStream.Play.StreamNotFound":break; } } // play a recorded stream on the server private function doVideo(nc:NetConnection):void { ns = new NetStream(nc); ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); video = new Video(640,480); video.attachNetStream(ns); ns.play("myCamera"); addChild(video); } // create a playlist on the server/* private function doPlaylist(nc:NetConnection):void { ns = new NetStream(nc); ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); video = new Video(); video.attachNetStream(ns); // Play the first 3 seconds of the video ns.play( "bikes", 0, 3, true );// Play from 20 seconds on ns.play( "bikes", 20, -1, false);// End on frame 5ns.play( "bikes", 5, 0, false ); addChild(video); }*/ }}
simplest_as3_local_player
simplest_as3_local_player用於播放本地FLV檔案。ActionScript中播放本地視頻(*.flv)和播放RTMP流程是一樣的:先建立NetConnection,再建立NetStream。它們最大的不同在於,播放本地檔案建立NetConnection的時候,是不傳地址的。例如播放RTMP的時候代碼如下:
nc.connect("rtmp://localhost/live");
播放本地檔案的時候代碼如下:
nc.connect(null);
調用play()的時候,RTMP傳遞伺服器上的路徑,如下所示。
ns.play("myCamera");
本地檔案直接傳遞本地路徑,如下所示。
ns.play("sintel.flv");
simplest_as3_rtmp_player_multiscreen
simplest_as3_rtmp_player_multiscreen是一個多屏播放的簡單例子。實現了2x2網格播放4路視頻。不再過多記錄。
simplest_as3_rtmp_streamer
simplest_as3_rtmp_player是最簡單的RTMP推流器,代碼如下所示。
/** * 最簡單的基於ActionScript的RTMP推流器 * Simplest AS3 RTMP Streamer * * 雷霄驊 Lei Xiaohua * [email protected] * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程式使用ActionScript3語言完成,推送本地網路攝影機的資料至RTMP流媒體伺服器, * 是最簡單的基於ActionScript3的推流器。 * * This software is written in Actionscript3, it streams camera‘s video to * RTMP server. * It‘s the simplest RTMP streamer based on ActionScript3. * */package { import flash.display.MovieClip; import flash.net.NetConnection; import flash.events.NetStatusEvent; import flash.net.NetStream; import flash.media.Video;import flash.media.Camera; import flash.media.Microphone;//import flash.media.H264Profile; //import flash.media.H264VideoStreamSettings; public class simplest_as3_rtmp_streamer extends MovieClip {var nc:NetConnection;var ns:NetStream;var nsPlayer:NetStream;var vid:Video;var vidPlayer:Video;var cam:Camera;var mic:Microphone;var screen_w:int=320;var screen_h:int=240;public function simplest_as3_rtmp_streamer() {nc = new NetConnection();nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);nc.connect("rtmp://localhost/live"); }private function onNetStatus(event:NetStatusEvent):void{trace(event.info.code);if(event.info.code == "NetConnection.Connect.Success"){publishCamera();displayPublishingVideo();displayPlaybackVideo();}}private function publishCamera() {//Camcam = Camera.getCamera();/** * public function setMode(width:int, height:int, fps:Number, favorArea:Boolean = true):void * width:int — The requested capture width, in pixels. The default value is 160. * height:int — The requested capture height, in pixels. The default value is 120. * fps:Number — The requested capture frame rate, in frames per second. The default value is 15. */cam.setMode(640, 480, 15); /** * public function setKeyFrameInterval(keyFrameInterval:int):void * The number of video frames transmitted in full (called keyframes) instead of being interpolated by the video compression algorithm. * The default value is 15, which means that every 15th frame is a keyframe. A value of 1 means that every frame is a keyframe. * The allowed values are 1 through 300. */ cam.setKeyFrameInterval(25);/** * public function setQuality(bandwidth:int, quality:int):void * bandwidth:int — Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second (bps). * To specify that the video can use as much bandwidth as needed to maintain the value of quality, pass 0 for bandwidth. * The default value is 16384. * quality:int — An integer that specifies the required level of picture quality, as determined by the amount of compression * being applied to each video frame. Acceptable values range from 1 (lowest quality, maximum compression) to 100 * (highest quality, no compression). To specify that picture quality can vary as needed to avoid exceeding bandwidth, * pass 0 for quality. */cam.setQuality(200000, 90); /** * public function setProfileLevel(profile:String, level:String):void * Set profile and level for video encoding. * Possible values for profile are H264Profile.BASELINE and H264Profile.MAIN. Default value is H264Profile.BASELINE. * Other values are ignored and results in an error. * Supported levels are 1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5, and 5.1. * Level may be increased if required by resolution and frame rate. *///var h264setting:H264VideoStreamSettings = new H264VideoStreamSettings(); // h264setting.setProfileLevel(H264Profile.MAIN, 4); //Micmic = Microphone.getMicrophone();/* * The encoded speech quality when using the Speex codec. Possible values are from 0 to 10. The default value is 6. * Higher numbers represent higher quality but require more bandwidth, as shown in the following table. * The bit rate values that are listed represent net bit rates and do not include packetization overhead. * ------------------------------------------ * Quality value | Required bit rate (kbps) *------------------------------------------- * 0 | 3.95 * 1 | 5.75 * 2 | 7.75 * 3 | 9.80 * 4 | 12.8 * 5 | 16.8 * 6 | 20.6 * 7 | 23.8 * 8 | 27.8 * 9 | 34.2 * 10 | 42.2 *------------------------------------------- */mic.encodeQuality = 9; /* The rate at which the microphone is capturing sound, in kHz. Acceptable values are 5, 8, 11, 22, and 44. The default value is 8 kHz * if your sound capture device supports this value. Otherwise, the default value is the next available capture level above 8 kHz that * your sound capture device supports, usually 11 kHz. * */mic.rate = 44; ns = new NetStream(nc);//H.264 Setting//ns.videoStreamSettings = h264setting; ns.attachCamera(cam);ns.attachAudio(mic);ns.publish("myCamera", "live");}private function displayPublishingVideo():void {vid = new Video(screen_w, screen_h);vid.x = 10;vid.y = 10;vid.attachCamera(cam);addChild(vid);}private function displayPlaybackVideo():void{nsPlayer = new NetStream(nc);nsPlayer.play("myCamera");vidPlayer = new Video(screen_w, screen_h);vidPlayer.x = screen_w + 20;vidPlayer.y = 10;vidPlayer.attachNetStream(nsPlayer);addChild(vidPlayer);}}}
結果
simplest as3 rtmp player運行後會自動連接RTMP URL:rtmp://localhost/live/myCamera。
程式運行後的結果如所示。
simplest_as3_local_player運行會播放sintel.flv檔案。
運行結果如所示。
simplest_as3_rtmp_player_multiscreen運行後會串連4個RTMP URL。
運行結果如所示。
simplest_as3_rtmp_streamer運行結果後會推送原生網路攝影機的視頻和麥克風的音頻到指定的RTMP URL(在這裡是rtmp://localhost/live/myCamera)。左側的視頻是從網路攝影機讀取的視頻,右側的視頻是推流後從RTMP URL讀取的視頻(一般會有一定延時)。
運行結果如所示。
下載
Simplest flashmedia example
SourceForge:https://sourceforge.net/projects/simplestflashmediaexample/
Github:https://github.com/leixiaohua1020/simplest_flashmedia_example
開源中國:http://git.oschina.net/leixiaohua1020/simplest_flashmedia_example
CSDN下載:http://download.csdn.net/detail/leixiaohua1020/8456441
本工程包含如下基於Flash技術的流媒體的例子:
simplest_as3_rtmp_player: 最簡單的RTMP播放器(基於ActionScript)
simplest_as3_rtmp_streamer: 最簡單的RTMP推流器(基於ActionScript)
rtmp_sample_player_adobe: 從Adobe Flash Media Sever提取出來的測試播放器
rtmp_sample_player_wowza: 從Wowza伺服器中提取出來的測試播放器
rtmp_sample_player_flowplayer: 基於FlowPlayer的RTMP/HTTP播放器(添加RTMP plugin)
rtmp_sample_player_videojs: 基於VideoJS的RTMP/HTTP播放器
rtmp_sample_player_jwplayer: 基於JWplayer的RTMP/HTTP播放器
hls_sample_player_flowplayer: 基於FlowPlayer的HLS播放器(添加HLS plugin)
hls_video_player_html5: 基於HTML5的HLS/HTTP播放器
activex_vlc_player: 基於VLC的ActiveX控制項的播放器
注意:某些播放器直接開啟html頁面是不能工作的,需要把播放器放到Web伺服器上。
(例如Apache或者Nginx)
最簡單的基於Flash的流媒體樣本:RTMP推送和接收(ActionScript)