2012-01-04 102 views
2

這是我的第一個問題:D,首先抱歉我的英語。如何將MovieClip(位圖和音頻)保存到FLV?

我的問題基本上是如何保存Flash影片剪輯到FLV。

影片剪輯是由用戶生成的,它有各種聲音和動畫,我需要保存一個FLV發送給Youtbue。

我試過了什麼: 我在這裏發現了一些關於使用Alchemy Lib的問題,我正在使用它來抓取Movie Clip幀並保存到Bitmap。

Alchemy Lib將這些幀轉換爲像FLV一樣的魅力,並支持使用ByteArray保存聲音塊。

在這種情況下,我的問題是,我怎麼能抓住電影剪輯的聲音發送給鍊金術寶? 從來就嘗試使用:

SoundMixer.computeSpectrum(sndData, false, 2); 

女巫返回我sndData變量的ByteArray但無用的,因爲用於it's呈現在屏幕上的音頻波形。

阿布德吼聲使用

Sound.extract(); 

,但我認爲那聲音類只能用於一個MP3的聲音,我需要抓住的影片剪輯產生的混合聲音。

是否有另一種方法從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(); 


} 
+0

爲什麼你需要特別的FLV?你在使用Flash IDE嗎?如果是這樣,您可以將該電影導出爲AVI(文件|導出|「導出電影...」)並以這種方式將其上傳到YouTube。 – iND 2012-01-06 19:09:51

+0

目前沒有可能,因爲MovieClip只有soundTransform屬性,但無法訪問其聲音對象。也許Adobe意向沒有添加該功能,所以沒有人能夠在AS3中創建自己的swf2flv導出器。 – 2012-01-07 11:37:16

+0

我有一個想法如何做到這一點很難:它可能是聲音數據與MovieClip對象存儲在一起,所以你可能會嘗試序列化爲字節數組,然後挖掘字節碼來找到聲音數據並提取它:) – 2012-01-07 17:20:17

回答

1

做到了! (呃...差不多:D)

這很複雜,但由於我的問題只是MovieClip的音頻,我創建了一個類似混音器的類。

調音臺負責使用獨特的SampleDataEvent播放所有聲音,混合所有聲音的字節。當我執行startRecording函數時,它還會在ByteArray中生成單個聲音數據。 Kind很複雜的解釋,但這裏是混音器的代碼:

/**** 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用於播放並同時提取混合聲音。

我還必須創建一個擴展聲音對象,以便在由的ProcessSampleData方法中使用當前緩衝器來提取()方法getSampleData()每個聲音的一個的sampleData類爲mySound。 MySound類也會在混音器啓動時開始播放(發送兩個頻道的0字節),並且在混音器停止時也會停止,只有在調用播放()函數時纔會開始發送音樂的字節信息。

,我已創建的類是這樣的:

/**** 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信息傳遞給Alchemy Lib的addFrame(bitmapData,sndData),成功記錄它。

它在我的項目中運行良好,但我可能需要優化代碼。

謝謝所有幫助我的傢伙!