承上一篇,在下載錄音內容之前,先將它測試性的重播一次吧!
//播放URL的內容
void playAudio(String url) {
final audio = html.AudioElement()
..src = url
..autoplay = true
..play();
}
//產生本地端URL後丟給上面的函數播放
final url = html.Url.createObjectUrl(blob);
print(url);
playAudio(url);
OK!可以播放,看來「資料」本身是沒問題的!
但是...下載後的檔案無法在其他播放器中播放啊!
這是因為AI寫的程式碼幫我們存起來的是種叫做「raw data」的東西,(因為raw的意思同「生肉」,所以有時後這種資料會被戲稱為「生肉」。)
任何資料(不管是圖檔、文檔、影片、甚至程式本身)在raw data型態看起來都是一樣的!(就是0跟1,)必須要具備特定「格式」的「檔頭」(用非常特殊且固定的順序組成的0跟1)才能「辨識資料的型態」和「知道該用什麼樣的播放器播放」。(這段描述不是很正確,有很多需要修正釐清的細節。)
仔細看一下目前為止完成的所有功能...
存起來的檔案沒有檔頭無誤!
那接下來繼續問AI啦!
「為何檔案無法被外部播放器播放?」
還真告訴我答案啦!
「WAVE檔其實是種格式為PCM的檔案包裝,而PCM又包含了個種RIFF格式的檔案。」講得挺饒舌,但簡單來說就是要取得「PCM」或「RIFF」的檔案格式,或是包裝的辦法。
這裡快轉一下....簡單來說,Flutter上並沒有可靠的、產生PCM格式檔案的功能或是套件,所以想要這樣做就必須要自己幫檔案加上格式化。
那....「有幫raw資料加上PCM/RIFF格式的辦法嗎?」
還真的有!
ByteData createRiffHeader(int fileSize, int audioFormat, int numChannels, int sampleRate, int byteRate, int blockAlign, int bitsPerSample) {
var buffer = ByteData(44); // RIFF header size is 44 bytes
// "RIFF"
buffer.setUint8(0, 0x52);
buffer.setUint8(1, 0x49);
buffer.setUint8(2, 0x46);
buffer.setUint8(3, 0x46);
// File size
buffer.setUint32(4, fileSize, Endian.little);
// "WAVE"
buffer.setUint8(8, 0x57);
buffer.setUint8(9, 0x41);
buffer.setUint8(10, 0x56);
buffer.setUint8(11, 0x45);
// "fmt "
buffer.setUint8(12, 0x66);
buffer.setUint8(13, 0x6d);
buffer.setUint8(14, 0x74);
buffer.setUint8(15, 0x20);
// Subchunk size
buffer.setUint32(16, 16, Endian.little);
// Audio format
buffer.setUint16(20, audioFormat, Endian.little);
// Number of channels
buffer.setUint16(22, numChannels, Endian.little);
// Sample rate
buffer.setUint32(24, sampleRate, Endian.little);
// Byte rate
buffer.setUint32(28, byteRate, Endian.little);
// Block align
buffer.setUint16(32, blockAlign, Endian.little);
// Bits per sample
buffer.setUint16(34, bitsPerSample, Endian.little);
// "data"
buffer.setUint8(36, 0x64);
buffer.setUint8(37, 0x61);
buffer.setUint8(38, 0x74);
buffer.setUint8(39, 0x61);
// Subchunk size
buffer.setUint32(40, fileSize - 36, Endian.little);
return buffer;
}
要使用這個函數,就必須要取得「Audio format」「Number of channels」「Sample rate」「Byte rate」「Block align」「Bits per sample」等資料....
去哪取啊????
繼續...啊!不!明天待續!