2012-07-24 236 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服务器上的另一个文件。