前言:
移動端應用, 須要省電省流量(帶寬), 大資源包對用戶體驗是有傷害的. 所以移動端開發須要精簡資源(音頻/圖片), 但又要保證音頻/圖片質量. 本文着重講述如何優化處理資源(音頻/圖片), 如何在高壓縮比和高質量(音質/畫質)之間進行折中和權衡. 本文涉及兩大塊, 一塊爲語音處理, 另外一塊爲圖像處理.php
注: 本文主要面向移動端開發者, 利用編程去優化處理. 摻雜了小編(mumuxinfei)的不成熟觀點和見解, 但願能拋磚引玉. java
*) 樣例闡釋:
1. 構造應用場景
把常規Wav格式的音頻文件, 轉化爲更小的Mp3格式音頻文件.
樣例代碼藉助JAVE(Java Audio Video Encoder)來實現. 請點擊: JAVE官網.sql
File source = new File("data/source.wav"); File target = new File("data/target.mp3"); // *) 設置音頻屬性 AudioAttributes audio = new AudioAttributes(); audio.setCodec("libmp3lame"); audio.setBitRate(new Integer(128000)); audio.setChannels(new Integer(2)); audio.setSamplingRate(new Integer(44100)); // *) 解碼器設置 EncodingAttributes attrs = new EncodingAttributes(); attrs.setFormat("mp3"); attrs.setAudioAttributes(audio); Encoder encoder = new Encoder(); encoder.encode(source, target, attrs);
2. 效果展現
Wav格式轉化爲Mp3格式後, 實際大小對好比下所示:
Wav格式文件: 100044byte, Mp3格式文件: 18839byte
通過小編的親身體驗(試聽), 立場堅決的表示音質無明顯差異, 但文件壓縮比卻有明顯的提高.
3. 疑惑和不解
雖然大獲成功, 可是小編仍是有些不解, 疑問一坨坨. -_-!!!
#) 音頻文件中的比特率(bitrate), 聲道(channel), 採樣率(samplingrate)具體是什麼?
#) 在文件壓縮和音質中, 那個要素扮演更重要的角色? 是他, 是她, 仍是它? 唉, 個人媽呀, 小編我傻傻分不清了.
小編手濺, 因而修改下代碼, 取取不一樣的比特率/採樣率值, 看看是否有驚喜會出現?編程
// *) 設置音頻屬性 AudioAttributes audio = new AudioAttributes(); audio.setCodec("libmp3lame"); //audio.setBitRate(new Integer(128000)); audio.setBitRate(new Integer(250000)); audio.setChannels(new Integer(2)); //audio.setSamplingRate(new Integer(44100)); audio.setSamplingRate(new Integer(40000));
我樂個大擦, "驚喜"出現了, -_-!!!!!!! 竟然罷工, 還拋異常, 拋,拋,拋,拋你妹啊.....app
Exception in thread "main" it.sauronsoftware.jave.EncoderException: Error while opening codec for output stream #0.0 - maybe incorrect parameters such as bit_rate, rate, width or height
小編不禁得困惑了, 莫非比特率和採樣率有某種神祕的關係? 你看, 他兩結尾都帶個了'率'字, 並且讀起來又都那麼朗朗上口? 搞基不(MD, 不當心說出了內心話)? 算了, 其實小編心裏仍是小小期待下, oh yeah.
And 疑惑繼續....
#) 比特率和採樣率的取值是否有必定的限制?
#) 比特率和採樣率究竟存在怎麼樣關係呢?ide
*) 基礎知識
真是好奇心害死貓, 小編帶着這些疑團去知(姿)識(勢)淵(豐)博(富)的百度君.post
小編: 百度君,你好,你能給咱們介紹下音頻文件中的比特率(bitrate), 聲道(channel), 採樣率(samplingrate)具體是什麼?
百度君: #%~!@#$%^&*()~&(@!*^!@&*^*&%(*%&^%^$~!*)()*)@&(*^@#(*^(!&(!^(優化
小編(怒): 講人話......
百度君:
音頻文件有三個重要的屬性描述: 採樣率(samplingrate)/比特率(bitrate)/聲道(channel)
#)比特率:音頻數據每秒中須要多少個比特來表示,比特率越高音頻質量越好, 文件也越大.
#)採樣率:採樣率定義了每秒從連續信號中提取並組成離散信號的採樣個數,用赫茲(Hz)來表示.
#)聲道:聲道分單聲道, 雙聲道兩種, 單聲道是混合均勻從左右聲道出來, 而雙聲道則是從不一樣聲音
從左右聲道出來併合成, 現場立體感強.
小編(心裏):哼,百度君果真吃軟怕硬,不過好像說的好專業,不明覺厲.ui
小編:那請問比特率和採樣率的取值有限定嗎?
百度君:
#) 比特率取值
比特率取值: 32kbps/96kbps/128kbps/192kbps/224kbps/320kbps
#) 採樣率的取值
44.1kHz系列採樣: 11.025kHz, 22.05kHz, 44.1kHz, 88.2kHz, 176.4kHz
48kHz系列採樣: 12kHz, 24kHz, 48kHz, 96kHz, 192kHz
小編(心裏):這下長見識了,之後叫你還拋,拋,拋不了你妹了,娃哈哈, 喂, 說你呢? 看什麼看, 還看!!!!編碼
小編:那請問,這個44.1kHz有特殊來由嗎?
百度君:人類的聽覺波段在20Hz到20kHz, 由Nyquist採樣定理, 採樣評率只要超過信號帶寬2倍就不會產生混迭. 而實際上音樂CD規範則採用44.1kHz(20kHz兩倍多)作爲採樣標準. 所以44.1kHz和人類的可聽波段有必定的關聯.
激動人心的時候, 終於要來了, 此時空氣彷彿凝固了....
小編(喜): 那比特率君和採樣率君究竟有何姦情呢? (啊呸, 居然不當心說漏嘴了......)
百度君: 兩個維度,互不影響. 簡而言之, 比特率用於音頻編碼過程當中, 而採樣率用於語音播放中. 比特率與音質成正比, 文件大小成反比. 而採樣率只與音質成正比.
天空一行烏鴉飛過, 哇哇哇.....
小編(心裏): 這TM是玩我嗎? 搞得這麼親熱, 還一直如影隨行, 最後居然告訴我,他倆沒半毛錢的關係, 這誰信啊!!!!!!
小編(失落): 真是個意外的結果, 萬萬沒想到, 這個世上仍是有純粹的友誼存在, 無論你信不信, 反正我是信了.
唉, 忽然以爲菊花好癢......
*) 進階篇
1). 查閱音頻文集元信息
如何藉助JAVE來實現, 代碼片斷以下:
MultimediaInfo info = encoder.getInfo(target); System.out.println(info);
Console 結果輸出以下:
(decoder=pcm_s16le, samplingRate=22050, channels=2, bitRate=705)
評註: 解碼器爲: pcm_s16le, 採樣率: 22.05kHz, 雙聲道, 比特率705Kbps
2). 嘗試把Wav轉化爲各個比特率的Mp3格式
採樣率/比特率 | 24kbps | 48kbps | 96kbps | 192kbps |
11.025kHz | 3792 | 7554 | 15077 | -- |
22.05kHz | 3636 | 7241 | 14451 | -- |
44.1kHz | -- | 7084 | 14137 | 28243 |
評註: 比對橫向/豎向, 能夠看到文件大小與比特率相關, 而採樣率和比特率之間有必定的組合限定.
3). 嘗試把Wa轉化爲各個解碼器的音頻格式
音頻的解碼器, 取決於音頻格式, 簡單羅列下:
mp3 => libmp3lame ogg => vorbis wav => pcm_s16be/pcm_s16le/pcm_s24le 3gp => libfaac
更多的解碼器, 請點擊: 官網
在相同條件(比特率:24kbps, 採樣率:22.05kHz, 雙聲道)
音頻格式 | mp3 | ogg | wav | 3gp |
文件大小 | 3636 | 6586 | 100044 | 2668 |
當在相同條件(比特率:48kbps, 採樣率:44.1kHz, 雙聲道)
音頻格式 | mp3 | ogg | wav | 3gp |
文件大小 | 7084 | 8722 | 199980 | 5177 |
評註: 能夠看出, 同等條件下文件大小: 3gp < mp3 < ogg << wav, 但文件壓縮比高不表明好, 最終須要在壓縮比/音質取個折中
圖像處理
移動端對圖片格式的選擇: 主流爲PNG/JPEG格式. PNG它兼具JPG圖片的質量和GIF格式的透明, 文件大小較JPEG大. JPEG格式畫質好, 色彩和飽和度高, 文件相對相對較小. 所以通常有以下實踐原則: 小尺寸, 色彩數小或使用到透明的時候用PNG, 大尺寸, 色彩漸變色多的時候用JPG.
移動端的圖片優化包括兩方面, 一塊爲圖片格式轉換, 一塊爲圖片像素大小調整.
代碼片斷:
public void convertImage(String sourceFile, String destFile, int newWidth, int newHeight) { // *) 假定傳入destFile, 都是 *.jpg, *.png 的命名方式, 這邊不作檢查處理 String format = destFile.substring(destFile.lastIndexOf('.') + 1); try { Image srcImage = ImageIO.read(new File(sourceFile)); // *) 繪製源圖像到目標圖像 BufferedImage destImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_3BYTE_BGR); Graphics2D g2 = (Graphics2D) destImage.getGraphics(); g2.drawImage(srcImage, 0, 0, newWidth, newHeight, null); // *) 生成目標圖像 ImageIO.write(destImage, format, new File(destFile)); } catch (IOException e) { e.printStackTrace(); } }
評註: 這段代碼能實現jpg=>png, jpg=>gif, jpg=>bmp, png=>jpg的轉換, 同時實現不一樣分辨率的圖像轉換
實驗比較, 原圖以下(秀福利)
文件大小比對以下:
圖片格式 | JPG | PNG | GIF | BMP |
文件大小 | 19.0KB | 267.9KB | 48.7KB | 386.8KB |
對比能夠發現, 等同像素下, 圖片文件大小爲 jpg < gif < png < bmp
繼續實驗, 把大分辨率圖像轉化爲小分辨率(主流分辨率)圖像, 壓縮率有多少
分辨率 | 1600*1200 | 1280*1024 | 1080*960 | 960*540 | 854*480 |
文件大小 | 251.7KB | 188.8KB | 157.7KB | 90.3KB | 74.7KB |
若是想更深刻的對圖像質量進行控制, (好比jpg圖像質量, 默認缺省質量爲0.75):
代碼片斷以下:
public void convert2JPGImage(String sourceFile, String destFile, int newWidth, int newHeight, float quality) { FileOutputStream out = null; try { Image srcImage = ImageIO.read(new File(sourceFile)); // *) 繪製源圖像到目標圖像 BufferedImage destImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_3BYTE_BGR); Graphics2D g2 = (Graphics2D) destImage.getGraphics(); g2.drawImage(srcImage, 0, 0, newWidth, newHeight, null); // *) 生成目標圖像, 藉助com.sun.image.codec.jpeg.JPEGImageEncoder來實現 out = new FileOutputStream(destFile); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(destImage); jep.setQuality(quality, true); encoder.encode(destImage, jep); } catch (IOException e) { } finally { if ( out != null ) { try { out.close(); } catch (IOException e) { } } } }
總結: 移動端開發須要必定的音頻/圖片優化技巧, 對資源類的app而言, 這一點就特別的重要. 文件壓縮比不是越高越好, 對高音質/高畫質的追求會付出必定的代價.總而言之: 沒有完美的解決方案, 只有永恆的折中.