|
|
(2 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| =LiveFeed Test= | | =LiveFeed Test= |
| + | <html> |
| <!DOCTYPE html> | | <!DOCTYPE html> |
− | <html> | + | <html lang="en"> |
| <head> | | <head> |
− | <meta charset="utf-8"> | + | <meta charset="UTF-8"> |
− | <meta content="stuff, to, help, search, engines, not" name="keywords"> | + | <meta name="viewport" content="width=device-width, initial-scale=1"> |
− | <meta content="What this page is about." name="description"> | + | <link rel="stylesheet" href="../../dependencies/bootstrap/css/bootstrap.css"> |
− | <meta content="Display Webcam Stream" name="title"> | + | <link rel="stylesheet" href="../../dependencies/bootstrap/font-awesome/css/font-awesome.min.css"> |
− | <title>Display Webcam Stream</title> | + | <link rel="stylesheet" href="jquery-ui.css"> |
− |
| + | <link rel="stylesheet" href="player.css"> |
− | <style> | + | |
− | #container {
| + | <title>Player</title> |
− | margin: 0px auto; | + | <script type="text/javascript" src="../../../../flashphoner.js"></script> |
− | width: 500px; | + | <script type="text/javascript" src="../../dependencies/jquery/jquery-1.12.0.js"></script> |
− | height: 375px; | + | <script type="text/javascript" src="../../dependencies/jquery/jquery-ui.js"></script> |
− | border: 10px #333 solid;
| + | <script type="text/javascript" src="../../dependencies/js/utils.js"></script> |
− | }
| + | |
− | #videoElement {
| + | <script type="text/javascript" src="player.js"></script> |
− | width: 500px; | + | <!-- Bootstrap JS --> |
− | height: 375px; | + | <script src="../../dependencies/bootstrap/js/bootstrap.js"></script> |
− | background-color: #666; | |
− | }
| |
− | </style> | |
| </head> | | </head> |
− |
| + | <body onload="init_page()"> |
− | <body> | + | <div class="container"> |
− | <div id="container"> | + | <div class="row"> |
− | <video autoplay="true" id="videoElement"> | + | |
− |
| + | <h2 class="text-center col-sm-10">Player</h2> |
− | </video> | + | |
| + | <h2 id="notifyFlash" class="text-danger"></h2> |
| + | |
| + | <div class="col-sm-10 text-center"> |
| + | <div class="fp-remoteVideo"> |
| + | <div class="display" id="remoteVideo"> |
| + | <i id="preloader" class="fa fa-spinner fa-pulse fa-3x fa-fw" aria-hidden="true" style="position: absolute; top: 43%; left: 47.5%;"></i> |
| + | </div> |
| + | </div> |
| + | |
| + | </div> |
| + | <div class="col-sm-8 text-center col-sm-offset-2" style="margin-top: 20px"> |
| + | <form id="form" class="form-horizontal" role="form" style="margin-top: 10px"> |
| + | <div id="connForm" class="form-group"> |
| + | <label class="col-sm-2 control-label">WCS URL</label> |
| + | <div class="col-sm-4"> |
| + | <input type="text" class="form-control" id="url"> |
| + | </div> |
| + | </div> |
| + | <div id="playForm" class="form-group"> |
| + | <label class="col-sm-2 control-label">Stream</label> |
| + | <div class="col-sm-4"> |
| + | <input type="text" class="form-control" id="streamName"> |
| + | </div> |
| + | </div> |
| + | <div id="volume" class="form-group"> |
| + | <label class="col-sm-2 control-label">Volume</label> |
| + | <div class="col-sm-4" style="height: 34px !important;"> |
| + | <div id="volumeControl" style="margin-top: 12px"></div> |
| + | </div> |
| + | </div> |
| + | <div id="fullScreen" class="form-group"> |
| + | <label class="col-sm-2 control-label">Full Screen</label> |
| + | <div class="col-sm-1" > |
| + | <button type="button" class="btn btn-default btn-sm" id="fullScreenBtn"> |
| + | <span class="glyphicon glyphicon-fullscreen"></span> |
| + | </button> |
| + | </div> |
| + | </div> |
| + | <div class="form-group"> |
| + | <div class="col-sm-4 control-label"> |
| + | <div id="status"></div> |
| + | <div id="info"></div> |
| + | </div> |
| + | <div class="col-sm-2 text-right"> |
| + | <button id="playBtn" type="button" class="btn btn-default">Start</button> |
| + | </div> |
| + | </div> |
| + | </form> |
| + | </div> |
| + | </div> |
| + | <div class="row" style="margin-top: 70px;"> |
| + | <div class="col-sm-4"> |
| + | <a href="https://play.google.com/store/apps/details?id=com.flashphoner.wcsexample.player"><img src="../../dependencies/img/google_play.jpg" title="Google Play" alt="Google Play"></a> |
| + | </div> |
| + | </div> |
| </div> | | </div> |
− | <script>
| |
− | var video = document.querySelector("#videoElement");
| |
− |
| |
− | if (navigator.mediaDevices.getUserMedia) {
| |
− | navigator.mediaDevices.getUserMedia({video: true})
| |
− | .then(function(stream) {
| |
− | video.srcObject = stream;
| |
− | })
| |
− | .catch(function(err0r) {
| |
− | console.log("Something went wrong!");
| |
− | });
| |
− | }
| |
− | </script>
| |
| </body> | | </body> |
| </html> | | </html> |
− | ==2==
| |
− | <html><?xml version="1.0" encoding="utf-8"?>
| |
− | <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
| |
− | xmlns:s="library://ns.adobe.com/flex/spark"
| |
− | xmlns:mx="library://ns.adobe.com/flex/mx"
| |
− | xmlns:views="rtmfptest.views.*"
| |
− | backgroundColor="#F2F0F0"
| |
− | width="450"
| |
− | height="592" creationComplete="init()" xmlns:local="*">
| |
− | <fx:Declarations>
| |
− |
| |
− | </fx:Declarations>
| |
− |
| |
− | <fx:Style>
| |
− | .header {
| |
− | fontSize: 36px;
| |
− | }
| |
− | </fx:Style>
| |
− |
| |
− | <fx:Script>
| |
− | <![CDATA[
| |
− | import mx.core.UIComponent;
| |
− | import mx.utils.StringUtil;
| |
− | private var nc:NetConnection;
| |
− | private var cam:Camera;
| |
− | private var mic:Microphone;
| |
− | private var videoFarEnd:Video;
| |
− | private var publishStream:NetStream;
| |
− | private var subscribeStream:NetStream;
| |
− | private var subscribeStreamObject:Object;
| |
− |
| |
− | private function init():void{
| |
− |
| |
− | if (ExternalInterface.available) {
| |
− | try {
| |
− | var href:String = ExternalInterface.call("window.location.href.toString");
| |
− | var hostname:String = ExternalInterface.call("window.location.hostname.toString");
| |
− | connectUrl.text = "rtmp://" + hostname + ":1935";
| |
− | } catch (error:Error) {
| |
− | Logger.info(error.message);
| |
− | }
| |
− | } else {
| |
− | Logger.info("Error during set callback");
| |
− | }
| |
− | cam = Camera.getCamera();
| |
− | videoMy.attachCamera(cam);
| |
− | mic = Microphone.getEnhancedMicrophone();
| |
− | videoFarEnd = new Video();
| |
− | var container:UIComponent = new UIComponent();
| |
− | container.addChild(videoFarEnd);
| |
− | canvas.addChild(container);
| |
− | playBtn.enabled = false;
| |
− | publishBtn.enabled = false;
| |
− | stopBtn.visible = false;
| |
− | unpublishBtn.visible = false;
| |
− | disconnectBtn.visible = false;
| |
− | var streamName:String = generateRandomString(4);
| |
− | publishStreamName.text = "Stream-"+streamName;
| |
− | playStreamName.text = "Stream-"+streamName;
| |
− |
| |
− | }
| |
− |
| |
− | // Reset button's state, clear status
| |
− | private function reset():void {
| |
− | connectBtn.visible = true;
| |
− | disconnectBtn.visible = false;
| |
− |
| |
− | unpublishBtn.visible = false;
| |
− |
| |
− | publishBtn.enabled = false;
| |
− | publishBtn.visible = true;
| |
− |
| |
− | playBtn.visible = true;
| |
− | playBtn.enabled = false;
| |
− |
| |
− | stopBtn.visible = false;
| |
− |
| |
− | setPublishStatus("");
| |
− | setPlayStatus("");
| |
− | }
| |
− |
| |
− | private function initCam():void{
| |
− | cam.setMode(int(camWidth.text),int(camHeight.text),int(camFPS.text),true);
| |
− | cam.setQuality(0,int(camQuality.text));
| |
− | cam.setKeyFrameInterval(int(camKeyFrame.text));
| |
− | cam.setMotionLevel(0,2000);
| |
− | Logger.info("Cam initizlized "+cam.width+"x"+cam.height);
| |
− | }
| |
− |
| |
− | private function initMic():void{
| |
− | var options:MicrophoneEnhancedOptions = new MicrophoneEnhancedOptions();
| |
− | options.mode = MicrophoneEnhancedMode.FULL_DUPLEX;
| |
− | options.echoPath = 128;
| |
− | options.nonLinearProcessing = true;
| |
− | mic.codec = SoundCodec.SPEEX;
| |
− | mic.encodeQuality = 5;
| |
− | mic.framesPerPacket=1;
| |
− | mic.gain=50;
| |
− | mic.setSilenceLevel(0,2000);
| |
− | mic.enhancedOptions = options;
| |
− | Logger.info("Mic initialized");
| |
− | }
| |
− |
| |
− | /**
| |
− | * **************************
| |
− | * CONNECT / DISCONNECT
| |
− | * **************************
| |
− | **/
| |
− | private function connect():void{
| |
− | var url:String = StringUtil.trim(connectUrl.text);
| |
− | Logger.info("connect " + url);
| |
− | nc = new NetConnection();
| |
− | //if (url.indexOf("rtmp") == 0){
| |
− | // nc.objectEncoding = ObjectEncoding.AMF0;
| |
− | //}
| |
− | nc.client = this;
| |
− | nc.addEventListener(NetStatusEvent.NET_STATUS, handleConnectionStatus);
| |
− | var obj:Object = new Object();
| |
− | obj.login = generateRandomString(20);
| |
− | obj.appKey = "flashStreamingApp";
| |
− | nc.connect(url,obj);
| |
− | }
| |
− |
| |
− |
| |
− |
| |
− | //disconnect
| |
− | private function disconnect():void{
| |
− | Logger.info("disconnect");
| |
− | nc.close();
| |
− | }
| |
− |
| |
− | private function handleConnectionStatus(event:NetStatusEvent):void{
| |
− | Logger.info("handleConnectionStatus: "+event.info.code);
| |
− | if (event.info.code=="NetConnection.Connect.Success"){
| |
− | Logger.info("near id: "+nc.nearID);
| |
− | Logger.info("far id: "+nc.farID);
| |
− | Logger.info("Connection opened");
| |
− | disconnectBtn.visible = true;
| |
− | connectBtn.visible = false;
| |
− | playBtn.enabled = true;
| |
− | publishBtn.enabled = true;
| |
− | setConnectionStatus("CONNECTED");
| |
− | } else if (event.info.code=="NetConnection.Connect.Closed" || event.info.code=="NetConnection.Connect.Failed"){
| |
− | nc.removeEventListener(NetStatusEvent.NET_STATUS,handleConnectionStatus);
| |
− | unpublish();
| |
− | stop();
| |
− | Logger.info("Connection closed");
| |
− | setConnectionStatus("DISCONNECTED");
| |
− | reset();
| |
− | }
| |
− | }
| |
− |
| |
− | private function setConnectionStatus(event:String): void {
| |
− | connectionStatus.text = event;
| |
− | }
| |
− |
| |
− | /**
| |
− | * *************************
| |
− | * PUBLISH / UNPUBLISH
| |
− | * *************************
| |
− | **/
| |
− | private function publish():void{
| |
− | if (publishStreamName.text == "") {
| |
− | publishStatus.text = "Empty stream name";
| |
− | publishStatus.setStyle("color","#FF0000");
| |
− | return;
| |
− | }
| |
− | publishStatus.setStyle("color","#000000");
| |
− | Logger.info("publish audio: "+publishAudio.selected+" video: "+publishVideo.selected);
| |
− | publishStream = new NetStream(nc);
| |
− | if (publishAudio.selected){
| |
− | initMic();
| |
− | publishStream.attachAudio(mic);
| |
− | Logger.info("Init audio stream");
| |
− | }
| |
− | if (publishVideo.selected){
| |
− | initCam();
| |
− | publishStream.attachCamera(cam);
| |
− | addH264();
| |
− | Logger.info("Init video stream");
| |
− | }
| |
− | addListenerAndPublish();
| |
− | Logger.info("Publishing");
| |
− |
| |
− | }
| |
− |
| |
− | //unpublish
| |
− | private function unpublish():void{
| |
− | Logger.info("unpublish");
| |
− | if (publishStream!=null){
| |
− | publishStream.close();
| |
− | }
| |
− | videoFarEnd.clear();
| |
− | }
| |
− |
| |
− | private function addListenerAndPublish():void{
| |
− | publishStream.videoReliable=true;
| |
− | publishStream.audioReliable=false;
| |
− | publishStream.useHardwareDecoder=true;
| |
− | publishStream.addEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus);
| |
− | publishStream.bufferTime=0;
| |
− | publishStream.publish(publishStreamName.text);
| |
− | }
| |
− |
| |
− | public function addH264():void{
| |
− | var videoStreamSettings:H264VideoStreamSettings = new H264VideoStreamSettings();
| |
− | videoStreamSettings.setProfileLevel(H264Profile.MAIN,H264Level.LEVEL_3_1);
| |
− | publishStream.videoStreamSettings = videoStreamSettings;
| |
− | }
| |
− |
| |
− | private function setPublishStatus(event:String): void {
| |
− | publishStatus.text = event;
| |
− | }
| |
− |
| |
− | /**
| |
− | * *************************
| |
− | * PLAY / STOP
| |
− | * *************************
| |
− | **/
| |
− | private function play():void{
| |
− | if (playStreamName.text == "") {
| |
− | playStatus.text = "Empty stream name";
| |
− | playStatus.setStyle("color","#ff0000");
| |
− | return;
| |
− | }
| |
− | playBtn.enabled = false;
| |
− | playStatus.setStyle("color","#000000");
| |
− | Logger.info("play");
| |
− | subscribeStream = new NetStream(nc);
| |
− | addListenerAndPlay();
| |
− | }
| |
− |
| |
− | private function stop():void{
| |
− | if (subscribeStream != null) {
| |
− | stopBtn.enabled = false;
| |
− | subscribeStream.close();
| |
− | subscribeStream = null;
| |
− | }
| |
− | subscribeStreamObject = null;
| |
− | videoFarEnd.visible = false;
| |
− | }
| |
− |
| |
− | private function addListenerAndPlay():void{
| |
− | subscribeStream.videoReliable=true;
| |
− | subscribeStream.audioReliable=false;
| |
− | subscribeStream.useHardwareDecoder=true;
| |
− | subscribeStream.addEventListener(NetStatusEvent.NET_STATUS, handleSubscribeStreamStatus);
| |
− | if (playStreamName.text.indexOf("rtsp://") != -1) {
| |
− | subscribeStream.bufferTime=0.5;
| |
− | } else {
| |
− | subscribeStream.bufferTime=0.0;
| |
− | }
| |
− | var soundTransform:SoundTransform = new SoundTransform();
| |
− | soundTransform.volume=0.7;
| |
− | subscribeStream.soundTransform = soundTransform;
| |
− | subscribeStreamObject = createStreamObject();
| |
− | subscribeStream.play(playStreamName.text);
| |
− | videoFarEnd.attachNetStream(subscribeStream);
| |
− | videoFarEnd.width = 320;
| |
− | videoFarEnd.height = 240;
| |
− | videoFarEnd.visible = true;
| |
− | }
| |
− |
| |
− | private function createStreamObject():Object{
| |
− | var ret:Object = new Object();
| |
− | ret.mediaSessionId = generateRandomString(8);
| |
− | ret.name = playStreamName.text;
| |
− | return ret;
| |
− | }
| |
− |
| |
− | private function generateRandomString(strlen:Number):String{
| |
− | var chars:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
| |
− | var num_chars:Number = chars.length - 1;
| |
− | var randomChar:String = "";
| |
− |
| |
− | for (var i:Number = 0; i < strlen; i++){
| |
− | randomChar += chars.charAt(Math.floor(Math.random() * num_chars));
| |
− | }
| |
− | return randomChar;
| |
− | }
| |
− |
| |
− | private function setPlayStatus(event:String): void {
| |
− | playStatus.text = event;
| |
− | }
| |
− |
| |
− | /**
| |
− | * ****************************
| |
− | * HANDLE CONNECTION STATE
| |
− | * ****************************
| |
− | **/
| |
− |
| |
− | private function handleStreamStatus(event:NetStatusEvent):void{
| |
− | Logger.info("handleStreamStatus: "+event.info.code);
| |
− | switch (event.info.code) {
| |
− | case "NetStream.Failed":
| |
− | Logger.info("Publish failed");
| |
− | if (publishStream!=null){
| |
− | publishStream.close();
| |
− | publishStream.removeEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus);
| |
− | publishStream=null;
| |
− | }
| |
− | videoFarEnd.clear();
| |
− | setPublishStatus("PUBLISH STREAM FAILED");
| |
− | break;
| |
− | case "NetStream.Publish.BadName":
| |
− | Logger.info("Bad streamName. Please publish stream with other name");
| |
− | setPublishStatus("PUBLISH STREAM FAILED");
| |
− | break;
| |
− | case "NetStream.Unpublish.Success":
| |
− | publishStream.removeEventListener(NetStatusEvent.NET_STATUS, handleStreamStatus);
| |
− | publishStream=null;
| |
− | setPublishStatus("UNPUBLISHED");
| |
− | publishBtn.visible = true;
| |
− | unpublishBtn.visible = false;
| |
− | break;
| |
− | case "NetStream.Publish.Start":
| |
− | setPublishStatus("PUBLISHING");
| |
− | publishBtn.visible = false;
| |
− | unpublishBtn.visible = true;
| |
− | break;
| |
− | }
| |
− | }
| |
− |
| |
− | private function handleSubscribeStreamStatus(event:NetStatusEvent):void{
| |
− | Logger.info("handleSubscribeStreamStatus: "+event.info.code);
| |
− | switch (event.info.code) {
| |
− | case "NetStream.Play.PublishNotify":
| |
− | case "NetStream.Play.Start":
| |
− | setPlayStatus("PLAYING");
| |
− | playBtn.visible = false;
| |
− | stopBtn.enabled = true;
| |
− | stopBtn.visible = true;
| |
− | break;
| |
− | case "NetStream.Play.UnpublishNotify":
| |
− | case "NetStream.Play.Stop":
| |
− | setPlayStatus("STOPPED");
| |
− | playBtn.enabled = true;
| |
− | playBtn.visible = true;
| |
− | stopBtn.visible = false;
| |
− | break;
| |
− | case "NetStream.Play.StreamNotFound":
| |
− | setPlayStatus("STREAM NOT FOUND");
| |
− | playBtn.enabled = true;
| |
− | playBtn.visible = true;
| |
− | stopBtn.visible = false;
| |
− | break;
| |
− | case "NetStream.Play.Failed":
| |
− | setPlayStatus("STREAM FAILED");
| |
− | playBtn.enabled = true;
| |
− | playBtn.visible = true;
| |
− | stopBtn.visible = false;
| |
− | break;
| |
− | }
| |
− | }
| |
− |
| |
− | private function asyncErrorHandler(event: AsyncErrorEvent):void{
| |
− | Logger.info("asyncErrorHandler: "+event);
| |
− | }
| |
− |
| |
− | private function securityErrorHandler(event: SecurityErrorEvent):void{
| |
− | Logger.info("securityErrorHandler: "+event);
| |
− | }
| |
− | public function ping():void{
| |
− | nc.call("pong", null);
| |
− | }
| |
− |
| |
− | public function OnDataEvent(data:Object):void{
| |
− | var message:Object = data.payload;
| |
− | Logger.info(message.body);
| |
− | }
| |
− |
| |
− | /**
| |
− | *************************
| |
− | * JavaScript callbacks
| |
− | *************************
| |
− | **/
| |
− |
| |
− | private function getDataFromJS(value:String):void {
| |
− | if (value != null || value != "") {
| |
− | connectUrl.text = value;
| |
− | }
| |
− | }
| |
− |
| |
− | ]]>
| |
− | </fx:Script>
| |
− | <s:Label x="96" y="34" width="265" styleName="header" text="Flash Streaming"/>
| |
− | <!-- connect / disconnect -->
| |
− | <s:Button id="connectBtn" x="325" y="93" width="90" label="Login" click="connect()"/>
| |
− | <s:TextInput id="publishStreamName" x="99" y="143" width="199" text="StreamName"/>
| |
− | <s:Button id="disconnectBtn" x="325" y="93" label="Logout" click="disconnect()" width="90" enabled="true"/>
| |
− | <s:TextInput id="connectUrl" x="99" y="93" width="200"/>
| |
− |
| |
− | <!-- publish / unpublish -->
| |
− | <s:Button id="publishBtn" x="326" y="143" label="Start" width="90" height="21" click="publish()" enabled="true"/>
| |
− | <s:CheckBox id="publishAudio" x="146" y="505" label="audio" selected="true" />
| |
− | <s:CheckBox id="publishVideo" x="223" y="505" label="video" selected="true"/>
| |
− |
| |
− | <s:Label x="120" y="561" text="width"/>
| |
− | <s:TextInput id="camWidth" x="120" y="531" width="32" text="320"/>
| |
− |
| |
− | <s:Label x="159" y="561" text="height"/>
| |
− | <s:TextInput id="camHeight" x="160" y="531" width="31" text="240"/>
| |
− |
| |
− | <s:Label x="206" y="561" text="fps"/>
| |
− | <s:TextInput id="camFPS" x="200" y="531" width="31" text="15"/>
| |
− |
| |
− | <s:Label x="240" y="561" text="quality"/>
| |
− | <s:TextInput id="camQuality" x="240" y="531" width="31" text="80"/>
| |
− |
| |
− | <s:Label x="279" y="561" text="keyframe"/>
| |
− | <s:TextInput id="camKeyFrame" x="280" y="531" width="31" text="15"/>
| |
− |
| |
− | <!-- play / stop -->
| |
− | <s:Button id="playBtn" x="325" y="193" label="Start" width="90" height="21" click="play()" enabled="true"/>
| |
− |
| |
− | <!-- video view -->
| |
− | <mx:Canvas id = "canvas" visible="true" x="65" y="257" width="320" height="240">
| |
− | <mx:VideoDisplay id="videoMy" visible="true" x="0" y="0" width="80" height="60" chromeColor="#EEA1A1"/>
| |
− | </mx:Canvas>
| |
− | <s:Label x="35" y="143" width="56" height="22" text="Publish" verticalAlign="middle"/>
| |
− | <s:Label x="35" y="93" width="89" height="22" text="Server:" verticalAlign="middle"/>
| |
− | <s:TextInput id="playStreamName" x="99" y="193" width="199" text="StreamName"/>
| |
− | <s:Label x="35" y="193" height="22" text="Play" verticalAlign="middle"/>
| |
− | <s:Button id="unpublishBtn" x="326" y="143" label="Stop" click="unpublish()" width="90" enabled="true"/>
| |
− | <s:Button id="stopBtn" x="325" y="193" label="Stop" width="90" height="21" click="stop()" enabled="true"/>
| |
− | <s:Label id="connectionStatus" x="123" y="119" width="150" height="20" textAlign="center"
| |
− | verticalAlign="top"/>
| |
− | <s:Label id="publishStatus" x="123" y="169" width="150" height="20" textAlign="center"
| |
− | verticalAlign="middle"/>
| |
− | <s:Label id="playStatus" x="123" y="219" width="150" height="20" textAlign="center"
| |
− | verticalAlign="middle"/>
| |
− | </s:Application></html>
| |