Date: 2016-03-23
Title: m4a文件在iOS上的流媒體播放
Tags: m4a, mp4, iOS, Android
URL: m4a-streaming-play-on-mobile-phonejava
公司項目中有個語音錄製與播放的功能,QA反饋有部分 Android 機型錄制的音樂文件沒法在 iOS 上進行播放。看了一下 iOS 的實現代碼,iOS 的實現有考慮當文件較大時先下載再播放引發的延遲,是按流形式播放的。git
找到出錯的 m4a 文件,發現若是按下載播放形式,不會出現任何問題;按流形式邊下邊播,會報錯:github
on-optimized formats not supported for streaming工具
m4a 文件本質就是一個mp4文件,m4a僅是聲明容器文件中僅含有音頻內容。mp4和QuickTime®文件同樣都是一種容器文件,相似XML那樣由若干個"Atom"組成,每一個 atom 文件中存放不一樣的meta、音頻數據、視頻數據、字幕等內容。而所謂 "optimize for streaming" 意指將文件中的 meta data 提到文件前部,這樣播放器按流形式讀取時,能夠在獲取音視頻數據前獲取具體的音視頻編碼信息。ui
mp4 和 QuickTime 能夠使用 Appple 公司的 Atom Inspector 工具打開:編碼
左邊的001.m4a 文件是播放出錯的 m4a 文件,能夠看到,用於存入音頻數據(AAC格式)的 mdata 牌ftyp 後,而存放 metadata 的 moov 處於文件的最後。atom
位於右邊的文件是使用iTunes轉換後的 m4a 文件,moov 段被移動到了文件前部,mdata 被放置於文件的最後。轉換後的m4a能夠正常按流形式進行播放。code
最初是想將文件轉換放到服務端來進行,讓它相似縮略圖生成那樣成爲一種文件擴展服務。可是,考慮 CS 團隊未必有時間立刻開發這個擴展功能而項目又等着急用,最後我仍是直接在 Android 中實現了這個 optimizing of Streaming 功能。orm
使用的是mp4parser Library。簡單的將文件使用 mp4parser
複製一下音軌便可,由於項目中爲用戶錄音,實際音軌只有一條,因此將那條音軌取出存入一個新文件便可。代碼以下:視頻
Movie originalMovie = MovieCreator.build(sourceM4a); Movie destMovie = new Movie(); Track audioTrack = originalMovie.getTracks().get(0); destMovie.addTrack(audioTrack); Mp4Builder builder = new DefaultMp4Builder(); Container container = builder.build(destMovie); container.writeContainer(new FileOutputStream(destM4a).getChannel());