[英]How Can I save a MovieClip (Bitmap and Audio) to FLV?
這是我的第一個問題:D,對不起我的英語。
我的問題基本上是如何將Flash Movie Clip保存到FLV。
電影剪輯是由用戶生成的,它具有各種聲音和動畫,我需要保存FLV才能將其發送到Youtbue。
我嘗試了什么:我在這里發現了一個有關使用煉金庫的問題,該庫用於抓取影片剪輯幀並將其保存到位圖。
Alchemy Lib像魅力一樣將那些幀轉換為FLV,並支持使用ByteArray保存聲音塊。
在這種情況下,我的問題是,我怎樣才能抓住Movie Clip的聲音將其發送到Alchemy Lib? 我嘗試使用:
SoundMixer.computeSpectrum(sndData, false, 2);
Witch在sndData變量中返回了一個byteArray,但它沒有用,因為它用於在屏幕上渲染Audio Wave表單。
Thougth aboud使用
Sound.extract();
但我相信聲音類別僅用於一種MP3聲音,我需要獲取Movie Clip生成的混合聲音。
是否有其他方法可以從MovieClip生成FLV?
下面是我的一些代碼:
我的代碼基於在此鏈接中找到的教程: http : //www.zeropointnine.com/blog/updated-flv-encoder-alchem/
private const OUTPUT_WIDTH:Number = 550;
private const OUTPUT_HEIGHT:Number = 400;
private const FLV_FRAMERATE:int = 24;
private var _baFlvEncoder:ByteArrayFlvEncoder;
public var anime:MovieClip;
//Starts recording
public function startRecording()
{
this.addEventListener(Event.ENTER_FRAME, enterFrame);
//Initialize the Alchemy Lib
_baFlvEncoder = new ByteArrayFlvEncoder(stage.frameRate);
_baFlvEncoder.setVideoProperties(OUTPUT_WIDTH, OUTPUT_HEIGHT);
_baFlvEncoder.setAudioProperties(FlvEncoder.SAMPLERATE_22KHZ);
_baFlvEncoder.start();
}
//Stops recording
public function stopRecording()
{
this.removeEventListener(Event.ENTER_FRAME, enterFrame);
_baFlvEncoder.updateDurationMetadata();
// Save FLV file via FileReference
var fileRef:FileReference = new FileReference();
fileRef.save(_baFlvEncoder.byteArray, "test.flv");
_baFlvEncoder.kill();
}
//The Main Loop activated by StartRecording
public function enterFrame(evt:Event)
{
var bmpData:BitmapData = new BitmapData(OUTPUT_WIDTH, OUTPUT_HEIGHT, false, 0xFFFFFFFF);
bmpData.draw(anime);
var sndData:ByteArray = new ByteArray();
SoundMixer.computeSpectrum(sndData, false, 2);
_baFlvEncoder.addFrame(bmpData, sndData);
bmpData.dispose();
}
完成了! (好吧...差不多:D)
這很復雜,但是由於我的問題只是MovieClip的音頻,所以我創建了一個像調音台的類。
調音台負責使用唯一的SampleDataEvent播放所有聲音,該聲音混合我所有聲音的字節。 當我執行startRecording函數時,它也會在ByteArray中生成單個聲音數據。 種類解釋起來很復雜,但這是攪拌機的代碼:
/**** MySoundMixer initializations omitted ***/
//Generates the sound object to start the stream
//for reproduce the mixed sounds.
public function startStream()
{
fullStreamSound= new Sound();
fullStreamSoundData = new ByteArray();
this.fullStreamSoundChannel = this.fullStreamSound.play();
}
//Adds a sound in the soundlib
//(See: MySound object for more details)
public function addSound(sound:MySound, key:String)
{
sound.initialize();
sounds.push({sound:sound, key:key});
}
//Play a sound in the sound lib
public function play(key)
{
var founded:MySound = null;
for (var i = 0; i < sounds.length; i++)
{
if (key == sounds[i].key)
{
founded = sounds[i].sound;
break;
}
}
if (founded != null)
{
founded.play();
}
}
// The SampleDataEvent function to Play the sound and
// if recording is activated record the sound to fullStreamSoundData
public function processSampleData(event:SampleDataEvent)
{
var pos = 0;
var normValue:Number = 1 / this.sounds.length;
while (pos < BUFFER)
{
var leftChannel:Number = 0;
var rightChannel:Number = 0;
for (var i = 0; i < this.sounds.length; i++)
{
var currentSound:MySound = this.sounds[i].sound;
var result = currentSound.getSampleData();
leftChannel += result.leftChannel * normValue;
rightChannel += result.rightChannel * normValue;
}
event.data.writeFloat(leftChannel);
event.data.writeFloat(rightChannel);
if (isRecording)
{
fullStreamSoundData.writeFloat(leftChannel);
fullStreamSoundData.writeFloat(rightChannel);
}
pos++;
}
}
//Starts recording
public function startRecording()
{
this.isRecording = true;
}
//Stops recording
public function stopRecording()
{
this.isRecording = false;
}
SampleDataEvent用於播放並同時提取混合的聲音。
我還必須創建一個MySound類,該類擴展了Sound對象,以便在processSampleData方法使用的當前緩沖區中提取每種聲音的sampleData(方法getSampleData() )。 MySound類也將在混音器啟動時開始播放(兩個通道都發送0字節),並且在混音器停止時也將停止,它僅在調用play()函數時才開始發送音樂的字節信息。
我創建的類是這樣的:
/**** MySound initializations omitted ***/
public function initialize()
{
this.extractInformation(null);
}
//Override the play function to avoid playing.
//(The play act will be triggered by SoundMixer class)
override public function play(startTime:Number = 0, loops:int = 0, sndTransform:SoundTransform = null):SoundChannel
{
this.isPlaying = true;
this.currentPhase = 0;
return null;
}
// On each buffer in sampledata i read the chunk of sound bytes
public function getSampleData()
{
var leftChannel:Number = 0;
var rightChannel:Number = 0;
if (this.isPlaying) {
if (currentPhase < totalPhases)
{
this.soundData.position = currentPhase * 8;
leftChannel = this.soundData.readFloat();
rightChannel = this.soundData.readFloat();
this.currentPhase ++;
} else
{
stopPlaying();
}
}
return { leftChannel:leftChannel, rightChannel:rightChannel };
}
//Extracts information of the sound object in order to
//split it in several chunks of sounds.
public function extractInformation(evt:Event)
{
trace("Inicializando o som " + this.id3);
this.soundData = new ByteArray();
this.extract(soundData, int(this.length * SAMPLE_44HZ + 10000));
this.totalPhases = this.soundData.length / 8;
this.currentPhase = 0;
}
///Stop playing means stop extracting bytes
public function stopPlaying()
{
this.isPlaying = false;
}
這樣,我生成了一個唯一的ByteArray對象,其中包含混音器的空洞聲音信息。 我要做的就是在動畫片段啟動時啟動混音器,在動畫片段停止時也停止混音器。 帶有聲音對象的ByteArray信息將傳遞到Alchemy Lib的addFrame(bitmapData,sndData)中,並成功將其記錄下來。
它在我的項目中運行良好,但是我可能需要優化代碼。
謝謝所有幫助我的人!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.