最简单的基于Flash的流媒体示例:RTMP推送和接收(ActionScript)

本文记录一些基于Flash的流媒体处理的例子。Flash平台最常见的流媒体协议是RTMP。此前记录的一些基于C/C++的RTMP播放器/推流器,但是没有记录过基于Flash中的ActionScript的RTMP播放器/推流器。其实基于Flash的RTMP播放器/推流器才能算得上是RTMP技术中的“正规军”。RTMP本身设计出来就是用于Flash平台之间通信的,而且RTMP最大的优势——“无插件直播”,也是得益于广泛安装在客户端的Flash Player。因此本文分别记录一个基于ActionScript的RTMP播放器和基于ActionScript的RTMP推流器。

基于C/C++的RTMP流媒体处理的例子可以参考下面几个。

发布

最简单的基于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 5
			ns.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() {

			//Cam

			cam = 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);   

			//Mic

			mic = 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)

时间: 2024-10-16 21:56:10

最简单的基于Flash的流媒体示例:RTMP推送和接收(ActionScript)的相关文章

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

本文继续上一篇文章,记录一些基于Flash的流媒体处理的例子.本文记录一些基于Flash技术的网页播放器.基于Flash的网页播放器相比于其他网页播放器来说最大的优势就是"免插件安装"了,这一点可以很大的提高用户的体验质量.早些时候网络视频(尤其是直播)一般都使用ActiveX控件作为视频播放器,而这些控件并不普及,所以终端用户必须下载相关的插件才能收看节目,因而对很多不熟悉电脑的用户造成了很大的障碍.直到Flash网页播放器的出现,这一障碍才得到了解决.本文将会记录几个常用的网页播放

【纵横科技】基于dwr框架的reverseajax消息推送 有图有图!

原文:[纵横科技]基于dwr框架的reverseajax消息推送 有图有图! 源代码下载地址:http://www.zuidaima.com/share/1584228052847616.htm\ 网络的最初设计是不允许服务器向浏览器发起连接,所以从浏览器及时的获取数据是个棘手的问题. 反向Ajax是具备有从web服务器向浏览器异步的发送数据的能力. 实现原理是保持客服端与服务器的长连接. 这里就附上一个简单的例子咯,给大家玩玩. 本人使用的是NetBeans编辑器,有不会转到MyEclipse

基于C++ 的苹果apns消息推送实现(2)

1.本模块使用C++ 和 Openssl 代码 实现了一个简单的apns客户端 2.本文的姐妹篇:基于boost 的苹果apns消息推送实现(1) 3.最初使用的sslv23/sslv2/sslv3只能和apple 建立连接,但一直是handshake失败, 最后换tls连接,握手成功! original_ssl_client.h #ifndef original_ssl_client_h #define original_ssl_client_h #pragma once #include <

基于微信的邮箱新邮件推送

基于微信的邮箱新邮件推送 最近主要做了2个东西: 合肥医保口罩购买预约网站分析 通过微信推送邮箱新邮件来信提醒 第一个因为网站已经下线,当时也没截图,导致想写过程,没素材.所以来写写通过微信推送邮箱的来信提醒. 一.背景 估计有人会问我在手机上登录邮箱账号,邮箱来信不自然能收到提醒吗? 主要是最近小丸子同学的公司邮箱在苹果手机上新邮件推送延迟.经常收到2天前的邮件提醒,如果不进入邮箱app主动收取邮件,根本不知道有邮件过来.对此小丸子同学也是跟我抱怨和很久,一直以为是手机坏了.最后分析了一下,确

简单、高效、易用的全平台(Windows/Linux/ARM/Android/iOS)web实现RTMP推送组件EasyRTMP-Android BUS传递消息过程介绍

背景分析 RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写,该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMP/RTMPS/RTMPE等多种变种.RTMP是一种设计用来进行实时数据通信的网络下ieyi,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信.RTMP推流,就是将直播内容推送到服务器的过程. EasyRTMP-Android BUS传递消息过程 提出问题EasyRTMP-Andro

基于socket.io的实时消息推送

用户访问Web站点的过程是基于HTTP协议的,而HTTP协议的工作模式是:请求-响应,客户端发出访问请求,服务器端以资源数据响应请求. 也就是说,服务器端始终是被动的,即使服务器端的资源数据发生变化,如果没有来自客户端的请求,用户就不会看到这些变化. 这种模式是不适合某些应用场景的,比如在社交网络用户需要近乎实时地知道其他用户最新的信息.对于普通站点来说, 请求-响应模式可以满足绝大多数的功能需求,但总有某些功能我们希望能够为用户提供实时消息的体验. 为解决这个问题,有两种方案可以选择: 仍旧使

基于Qt移动应用的消息推送服务原理与应用

说到移动应用,大家都觉得移动嘛,当然是Java和Object-c来做啦,什么推送啊,各种系统调用啊,其实不然?如果你了解Qt, 你就知道我说的不然,也有所道理. 说道几点 一.目前Android的移动的消息.通知推送 1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等.而且你还要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池. 2)SMS(Push)方式:在Android平

ASP.NET Core2基于RabbitMQ对Web前端实现推送功能

在我们很多的Web应用中会遇到需要从后端将指定的数据或消息实时推送到前端,通常的做法是前端写个脚本定时到后端获取,或者借助WebSocket技术实现前后端实时通讯.因定时刷新的方法弊端很多(已不再采用),所以基于WebSocket技术实现的通讯方案正越来越受大家喜爱,于是在ASP.NET中就有了鼎鼎大名的Signalr.但Signalr不是咱们这里的主角,这里将给大家介绍另一套基于WebSocket的前后端通讯方案,可以给大家在应用中多一个选择. 准备 在开始动手前,咱们先简单介绍下方案的组成部

基于boost 的苹果apns消息推送实现(1)

1. 为了当时测试,做了2份C++代码实现,一份是基于boost的实现 较完整,一份是C++加Openssl实现(可以用,不少细节需要调整) 2. 本模块只涉及apns客户端部分 3. 涉及boost的主要模块有boost bind,boost asio,boost ssl,boost deadline_timer, boost 正则表达式 4. 有一点需要注意,最初使用的sslv23/sslv2/sslv3只能和apple 建立连接,但一直是handshake失败,郁闷了相当长一段时间 最后换