Flash Media Server を使用して、Web カメラとマイクから記録し、FLV ファイルとして FMS サーバーに公開する事前作成済みのアプリケーションを作成しました。
これは問題なく動作しますが、iOS デバイスに記録されたこのビデオをストリーミングする必要があります。FMS が動作しており、hls-record/sample.f4v.m3u8 ファイルを iOS/quicktime デバイスにストリーミングできます。
オンラインでいくつかのチュートリアルを読み、publish(filename, "record") を publish("mp4:" + filename + ".f4v", record) に変更しました
レコードはファイルを FMS サーバーに保存します (そこに、私が指定したファイル名と .f4v ファイルとして表示されます)、コンテンツがあります。(クイックタイムまたはサファリ経由で)再生すると、ビデオの長さ(テストとして4秒)が表示されますが、ビデオは表示されません。トラッキング バーが動かず、待機アイコンが待機します。
私の Mac には FMS バージョン 4.5 と Flash 11.3 がインストールされています。(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()
}
}
}