2012-07-24 61 views
2

使用Flash Media Server,我有一個預製的應用程序,用於從網絡攝像頭和麥克風錄製並將其作爲FLV文件發佈到FMS服務器。將h.264從網絡攝像頭錄製爲f4v從閃存

這工作正常,但我現在需要將此視頻記錄到iOS設備。我有FMS工作,它可以將hls-record/sample.f4v.m3u8文件傳輸到iOS/QuickTime設備。

我在網上看了一些教程,我已經改變了發佈(文件名,「記錄」)發佈(「MP4:」 +文件名+「.f4v」,記錄)

它記錄存儲FMS服務器上的文件(我在那裏看到它,使用我給它的文件名和.f4v文件),它有內容。當我開始玩它時(通過quicktime或safari)我看到了視頻的長度(4秒作爲測試),但沒有視頻。跟蹤欄不移動,等待圖標等待。

FMS版本4.5和Flash 11.3安裝在我的Mac上。 (CentOS 5.8服務器)

我必須缺少一些東西。

package com 
{ 
import fl.controls.ProgressBar; 
import fl.controls.ProgressBarMode; 
import flash.display.MovieClip; 
import flash.events.Event; 
import com.NetConnector 
import flash.events.MouseEvent; 
import flash.events.TimerEvent; 
import flash.media.Camera; 
import flash.media.Microphone; 
import flash.media.Video; 
import flash.net.navigateToURL; 
import flash.net.NetConnection; 
import flash.net.NetStream; 
import flash.net.URLLoader; 
import flash.net.URLLoaderDataFormat; 
import flash.net.URLRequest; 
import flash.net.URLRequestMethod; 
import flash.net.URLVariables; 
import flash.text.TextField; 
import flash.utils.setTimeout; 
import flash.utils.Timer; 
import flash.media.H264Level; 
import flash.media.H264Profile; 
import flash.media.H264VideoStreamSettings; 
/** 
* ... 
* @author Alexander (flash2you) < > 
*/ 
public class Recorder extends MovieClip 
{ 
    private var dataHolder:DataHolder = DataHolder.getInstance() 

    public var layer:MovieClip 
    public var activityLevel_pb:ProgressBar 
    public var aguja:MovieClip 
    public var aguja2:MovieClip 
    public var publishButton:MovieClip 
    public var timer_txt:TextField 
    public var recordStatus:MovieClip 
    public var recordBtn:MovieClip 

    private var netStream:NetStream 
    private var microphone:Microphone = Microphone.getMicrophone() 
    private var camera:Camera = Camera.getCamera() 
    public var video:Video 

    private var timer:Timer = new Timer(100) 
    private var clockTimer:Timer = new Timer(1000) 

    public var published:Boolean = false 

    private var isRecording:Boolean = false 

    private var minutero = 0; 
    private var crono = 0; 
    private var records = 0; 


    public var settings_mc:MovieClip 
    public static var recorder:Recorder 
    public var settings_icon:MovieClip 

    private var limitTimer:Timer 
    public function Recorder() 
    { 
     Recorder.recorder = this; 

     timer.addEventListener(TimerEvent.TIMER, on$timer) 
     clockTimer.addEventListener(TimerEvent.TIMER, on$clockTimer) 
     //visible = false 


     recordBtn.buttonMode = true 
     recordBtn.addEventListener(MouseEvent.CLICK , recordBtn$click) 
     recordBtn.addEventListener(MouseEvent.MOUSE_OVER, recordBtn$over) 
     recordBtn.addEventListener(MouseEvent.MOUSE_OUT, recordBtn$out) 

     addEventListener(Event.ADDED_TO_STAGE, onAddedToStage) 


     limitTimer = new Timer(dataHolder.timelimit * 1000); 
     limitTimer.addEventListener(TimerEvent.TIMER, onLimitTimerHandler) 
    } 

    private function onLimitTimerHandler(e:TimerEvent):void 
    { 
     stopPublish() 
    } 
    /* 
    * when we comes to second frame 
    * */ 
    private function onAddedToStage(e:Event):void 
    { 
     removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); 

     init() 
    } 
    /* 
    * function for set up camera from settings module 
    * */ 
    public function setCamera(_camera:Camera) { 
     camera = _camera 
     addCameraSettings() 

     video.attachCamera(camera) 

     if (netStream){ 
      netStream.attachCamera(camera) 
     } 
    } 

    public function setMicrophone(mic:Microphone) { 
     microphone = mic; 

     if (netStream){ 
      netStream.attachAudio(microphone) 
     } 

     addMicSettings() 
    } 

    private function addMicSettings() { 
     microphone.setUseEchoSuppression(true); 
     microphone.setSilenceLevel(1) 
    } 

    private function addCameraSettings():void 
    { 
     camera.setQuality(90000, 90); 
     camera.setMode(320, 240, 30, true); 
     camera.setKeyFrameInterval(15); 
     //camera.setMode(dataHolder.cameraWidth, dataHolder.cameraHeight, dataHolder.cameraFPS) 
     //camera.setQuality(0, dataHolder.cameraQuality) 
    } 

    public function init() { 
     startConnect() 
    } 
    /* 
    * main function for connection 
    * */ 
    private function startConnect() { 
     visible = true 

     timer_txt.htmlText = "<b>00:00</b>"; 

     initCamera() 
     initMicropone() 
     var nc:NetConnection = new NetConnection() 
     nc.connect(null) 
     netStream = new NetStream(nc) 
     netStream.attachAudio(microphone) 

     video.attachCamera(camera) 
     layer.visible = false 


     publishButton.gotoAndStop(1); 


     activityLevel_pb.mode = ProgressBarMode.MANUAL; 

     recordStatus.gotoAndStop("noRecord") 

     timer.start() 


     connection.addEventListener(NetConnector.CONNECTED, connectionComplete) 
     connection.startConnection() 
    } 

    public function get connection():NetConnector { 
     return dataHolder.connection 
    } 

    private function on$timer(e:TimerEvent) { 
     activityLevel_pb.setProgress(microphone.activityLevel, 100) 
    } 
    /* 
    * when connection to your stream server done 
    * */ 
    private function connectionComplete(e:Event = null) { 
     netStream = new NetStream(connection) 
     netStream.attachAudio(microphone) 
     netStream.attachCamera(camera) 
    } 

    /* 
    * add 0 if less then 10secs 
    * */ 
    private function addLeading(nbr) { 
     if (nbr<10) { 
      return ("0"+Math.floor(nbr)); 
     } else { 
      return (Math.floor(nbr).toString()); 
     } 
    } 

    /* 
    * update visible clock, rotate arrows 
    * */ 
    private function updateTimer() { 
     timer_txt.htmlText = "<b>"+addLeading(crono/60)+":"+addLeading(crono%60)+"</b>"; 
     aguja.rotation = aguja.rotation+6; 
     if (addLeading(crono/60)>minutero) { 
      aguja2.rotation = aguja2.rotation+6; 
      ++minutero; 
     } 
     // end if 
     ++crono; 
    } 

    private function on$clockTimer(e:TimerEvent):void 
    { 
     updateTimer() 
    } 
    private function startClockTimer() { 
     clockTimer.start() 
    } 

    /* 
    * update graphics and start recording 
    * */ 
    private function recordBtn$click(e:MouseEvent):void 
    { 
     if (!isRecording) { 
      startRecording() 
      recordStatus.gotoAndStop("record") 
      recordBtn.visible = false 
     } 
    } 

    private function recordBtn$over(e:MouseEvent):void 
    { 
     if (!isRecording) { 
      this.gotoAndPlay(65); 
     } 
    } 
    private function recordBtn$out(e:MouseEvent):void 
    { 
     if (!isRecording) { 
      this.gotoAndPlay(61); 
     } 
    } 

    private function startRecording() { 
     if (connection.connected){ 

      var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings(); 
      h264Settings.setProfileLevel(H264Profile.BASELINE, H264Level.LEVEL_3_1); 


      netStream.videoStreamSettings = h264Settings; 

      netStream.publish("mp4:" + dataHolder.filename + ".f4v", "record"); 

      var metaData:Object = new Object(); 
      metaData.codec = netStream.videoStreamSettings.codec; 
      metaData.profile = h264Settings.profile; 
      metaData.level = h264Settings.level; 
      metaData.fps = camera.fps; 
      metaData.bandwith = camera.bandwidth; 
      metaData.height = camera.height; 
      metaData.width = camera.width; 
      metaData.keyFrameInterval = camera.keyFrameInterval; 
      metaData.copyright = "company"; 
      netStream.send("@setDataFrame", "onMetaData", metaData); 

     } 

     isRecording = true 
     startClockTimer() 

     publishButton.gotoAndPlay(2) 
     publishButton.buttonMode = true 
     publishButton.addEventListener(MouseEvent.CLICK, publishButton$click); 


     limitTimer.start() 
    } 

    /* 
    * redirect to finishURL that was passed via flashvars 
    * */ 
    private function publishButton$click(e:MouseEvent):void 
    { 
     stopPublish() 

     var request:URLRequest = new URLRequest(dataHolder.finishURL) 
     navigateToURL(request, "_self") 
    } 

    private function stopPublish():void 
    { 
     netStream.close(); 
     connection.close(); 

     limitTimer.stop(); 
     clockTimer.stop(); 

     isRecording = false 

     recordStatus.gotoAndStop("recordEnd") 

     updateTimer(); 
    } 
    /* 
    * init microphone 
    * */ 
    private function initMicropone():void 
    { 
     microphone = Microphone.getMicrophone() 
     addMicSettings() 
    } 
    /* 
    * init camera 
    * */ 
    private function initCamera():void 
    { 
     camera = Camera.getCamera() 
     addCameraSettings() 
    } 
} 
} 

回答

1

我已經決定創建一個與FLV文件一起放在文件夾中的php腳本。通過一個cron作業,這個php文件檢查mysql數據庫中是否有過程標籤爲1的新視頻。查找新視頻?在FLV文件上執行ffmpeg以將其轉換爲mp4並將過程標記設置爲0.這樣,我就可以維護用於桌面瀏覽器流式傳輸的FLV和用於iOS流式傳輸的MP4文件。如果我需要爲android創建另一種文件類型或其他任何可能出現的文件類型,我可以簡單地在cron作業觸發時執行另一個ffmpeg轉換。

這也會在服務器上造成較少的開銷。 mp4由ffmpeg編碼一次 - 並非每次請求通過FMS流式傳輸文件。現在,MP4只是Web服務器上的另一個文件。