簡體   English   中英

如何將MovieClip(位圖和音頻)保存到FLV?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM