Asterisk播放mp4(1)——音頻和PCM編碼

Asterisk現(xiàn)有版本不支持播放視頻文件(支持視頻通話),無法滿足發(fā)送視頻通知燕刻、視頻IVR等場景脸爱。本系列文章,通過學(xué)習(xí)音視頻的相關(guān)知識(shí)和工具昼丑,嘗試實(shí)現(xiàn)一個(gè)通過Asterisk播放mp4視頻文件的應(yīng)用呻逆。

本文分為四個(gè)部分:音頻基本概念,PCM編碼格式介紹菩帝,PCM A-law編碼格式介紹咖城,制作測試樣本。

音頻基本概念

image.png

我們聽到的聲音是由頻率(是什么)和強(qiáng)度(有多響)決定的呼奢。上圖是一個(gè)正弦函數(shù)生成的音頻宜雀,頻率是441Hz,采樣率是44.1kHz控妻,采樣(sample)的最大值是4095州袒。聲音的頻率就是一個(gè)完整的波形沒秒鐘重復(fù)的次數(shù),采樣率(sample_rate)是每秒鐘收集多少次聲音的強(qiáng)度數(shù)據(jù)弓候,這樣每個(gè)完整的波形包含100個(gè)采樣郎哭。

上面這個(gè)圖是個(gè)單聲道(channel)的音頻他匪,實(shí)際的音頻很多都是多聲道的。當(dāng)有多個(gè)聲道時(shí)夸研,需要定義每個(gè)聲道中的采樣用什么方式進(jìn)行排列邦蜜,例如:雙聲道的時(shí),可以LRLR...亥至,也可以LL...,RR...悼沈。(這個(gè)問題會(huì)在后續(xù)講容器的文章中在詳細(xì)說明)

每個(gè)采樣(sample)代表了聲音的強(qiáng)度,但它這并不是個(gè)絕對(duì)的聲音大小姐扮,只是相對(duì)的絮供。因?yàn)椋瑯拥穆曇粑募ㄟ^不同的設(shè)備播放茶敏,聲音的大小顯然不同壤靶,這個(gè)和播放設(shè)備提供的能量有關(guān)。聲音的絕對(duì)大小用分貝(dB)度量惊搏,采樣只是和分貝的相對(duì)關(guān)系贮乳。

PCM編碼

PCM(Pulse Code Modulation,脈沖編碼調(diào)制)是對(duì)聲音的振幅(音量的大刑窆摺)進(jìn)行編碼向拆,位深度為14bit,20bit酪耳,24bit等(用多少個(gè)二進(jìn)制位表示)浓恳。通過每秒鐘記錄若干次振幅的值(采樣率,8k碗暗,44.1k奖蔓,48k等),把聲音的波形記錄下來(頻率)讹堤。

計(jì)算機(jī)系統(tǒng)中8個(gè)二進(jìn)制位對(duì)應(yīng)1個(gè)字節(jié)吆鹤,所以實(shí)際表示一個(gè)采樣時(shí),需要用1個(gè)洲守,2個(gè)或4個(gè)字節(jié)進(jìn)行表示疑务;每個(gè)字節(jié)又可采用有符號(hào)或無符號(hào)的方式。當(dāng)用多個(gè)字節(jié)表示一個(gè)采樣時(shí)梗醇,又存在字節(jié)序的問題知允,就是前面的字節(jié)表示的高位還是低位,分為大字節(jié)序(big-endian叙谨,將高序字節(jié)存儲(chǔ)在起始地址)和小字節(jié)序(little-endian温鸽,將低序字節(jié)存儲(chǔ)在起始地址)。這樣就會(huì)產(chǎn)生 很多編碼的組合,下面是ffmpeg支持的pcm采樣格式(也可以通過命令行ffmpeg -formats | grep PCM查看)涤垫。

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double

    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar
    AV_SAMPLE_FMT_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar

    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

PCM A-law編碼

PCM本身是一種無損(lossless)編碼格式(我理解無損的含義是收集到什么就記錄什么姑尺,不同格式間的差別在于記錄的精度,并不因?yàn)榉绞疆a(chǎn)生的損失)蝠猬。但是在電話系統(tǒng)中為了更有效地傳遞數(shù)據(jù)切蟋,提出了PCM A-alawPCM mu-law兩種編碼格式,其思路是將原始的PCM編碼榆芦, 壓縮成8位的編碼(具體的算法不展開了柄粹,可以參考g711原理pcm轉(zhuǎn)alaw,pcm轉(zhuǎn)ulaw匆绣,alaw轉(zhuǎn)pcm驻右,ulaw轉(zhuǎn)pcm)。

alaw是將13位的有符號(hào)數(shù)壓縮為8位的有符號(hào)數(shù)崎淳,是有損編碼(壓縮)旺入,編碼后的數(shù)據(jù)通過解碼無法恢復(fù)到原狀,數(shù)值越大的采樣損失的數(shù)據(jù)就越多凯力。(這里有個(gè)疑問,在系統(tǒng)中是用16位保存一個(gè)樣本的礼华,那是否又有3位數(shù)據(jù)丟掉了咐鹤?)

alaw只定義了采樣的編解碼方法,但是實(shí)際使用中還要注意采樣率的問題圣絮,通常mp3祈惶,mp4這些音視頻文件中的采樣率為44.1k或48k,而電話系統(tǒng)中的采樣率為8k扮匠,那么從高采樣率到低采樣率捧请,必然又會(huì)產(chǎn)生損失。

制作樣本數(shù)據(jù)

image.png

上圖是實(shí)現(xiàn)Asterisk播放mp4文件的簡要流程棒搜,中間涉及到音頻的編解碼過程疹蛉,其中任何一個(gè)環(huán)節(jié)(出現(xiàn)錯(cuò)誤或者因?yàn)榫幗獯a帶來損失)都可能導(dǎo)致最終聽到的聲音有問題(失真,噪音等)力麸。我們必須找到一種方法驗(yàn)證在各個(gè)環(huán)節(jié)是否運(yùn)行正確可款,例如;采樣率克蚂,采樣位深度等等闺鲸。我采用的方法是通過ffmpeg這個(gè)工具生成測試數(shù)據(jù),并按照各個(gè)環(huán)節(jié)產(chǎn)生的編碼格式生成對(duì)應(yīng)的參照數(shù)據(jù)埃叭,然后比較在各個(gè)環(huán)節(jié)實(shí)際產(chǎn)生的數(shù)據(jù)是否正確摸恍。

pcm_s16le

通常mp4文件中的音頻解碼出的裸流是pcm_s16le(有符號(hào),2字節(jié)赤屋,小字節(jié)序)立镶,那么我們先生成一個(gè)該格式的10秒鐘的裸流壁袄。

ffmpeg -lavfi sine -t 10 -f s16le -c:a pcm_s16le sine-10s.s16le

image.png

ffmpeg告訴我們生成的文件的編碼格式pcm_s16le,采樣率是44100谜慌,單聲道mono然想。通過查看源碼(libavfilter/asrc_sine.c)可以知道:1、正弦波的頻率是441Hz欣范,那么每周期包含100個(gè)采樣(44100/441)变泄,這個(gè)有助于我們理解生成的數(shù)據(jù)的變化規(guī)律;2恼琼、采樣的最大值等于4095(0xfff)妨蛹,并不是有符號(hào)16位數(shù)的最大值32767(0x8000),這個(gè)最大值正好是12bit晴竞,加上1位符號(hào)位是13蛙卤,正好和alaw將13位有符號(hào)數(shù)轉(zhuǎn)為8位對(duì)應(yīng)上了。

生成文件的大小是882000字節(jié)噩死,44100個(gè)采樣/秒 * 10秒 * 2字節(jié)/采樣颤难。

讀取生成文件的前200個(gè)采樣(400個(gè)字節(jié))生成圖形如下:

image.png

按16進(jìn)制格式打開文件(vi sine-10s.s16le,打開后:%!xxd)已维,查看數(shù)據(jù):

image.png

可以看到在第26個(gè)采樣達(dá)到最大值ff0f行嗤,第76個(gè)采樣達(dá)到最小值01f0。因?yàn)槭切∽止?jié)序垛耳,要調(diào)換字節(jié)順序栅屏,所以最大值對(duì)應(yīng)的是0x0fff(4095),最小值對(duì)應(yīng)的是0xf001(-4095)堂鲜。

用上面的ffmpeg命令生成一段10秒鐘的pcm_s16le格式音頻文件(裸流栈雳,沒有進(jìn)行封裝)。我們既可以用耳朵聽缔莲,也可以用眼睛看這個(gè)音頻哥纫。

alaw

下面我們把同樣的聲音做alaw編碼。

ffmpeg -lavfi sine -t 10 -f alaw -c:a pcm_alaw sine-10s.alaw

image.png

生成文件的大小441000痴奏,44100個(gè)采樣/秒 * 10秒 * 2字節(jié)/采樣磺箕。

讀取生成文件的前200個(gè)采樣(200個(gè))字節(jié),生成圖形:

image.png

alaw采樣的符號(hào)位和原始pcm數(shù)據(jù)符號(hào)位是相反的抛虫,所以波峰和波谷和s16le是相反的松靡;因?yàn)閿?shù)據(jù)進(jìn)行了編碼壓縮,所以編碼后的數(shù)據(jù)并不能體現(xiàn)出原始波形建椰,但是頻率并沒有發(fā)生改變雕欺。

直接打開文件查看數(shù)據(jù):

image.png

可以看到在波峰波谷位置數(shù)據(jù)的差異變小了。

如果需要設(shè)置采樣率(默認(rèn)是44.1k),例如:8k屠列,可以通過ar參數(shù)實(shí)現(xiàn)啦逆。

ffmpeg -lavfi sine -t 10 -ar 8000 -f alaw -c:a pcm_alaw sine-8k-10s.alaw

alaw 轉(zhuǎn) s16le

alaw是一種壓縮格式,需要解壓縮才能播放笛洛,按alaw算法解碼出來的采樣時(shí)13位有符號(hào)數(shù)夏志,對(duì)應(yīng)的存儲(chǔ)格式就是pcm_s16le,所以我們看看alaw轉(zhuǎn)s16le會(huì)是什么樣苛让?

ffmpeg -f alaw -i sine-10s.alaw -f s16le -c:a pcm_s16le sine-alaw2s16le-10s.s16le

這次是用之前生成好的alaw文件作為輸入沟蔑。

image.png

取前200個(gè)樣本生成圖形。

image.png

從圖形上可以看到整體波形并沒有發(fā)生改變狱杰,但是在波峰波谷的位置存在失真瘦材,這表明alaw的編解碼過程帶來了損失。

image.png

查看原始數(shù)據(jù)我們也可以看到已經(jīng)和原始s16le數(shù)據(jù)不同仿畸,數(shù)據(jù)精度下降了食棕。

其他

其他ffmpeg命令

生成一段空白10秒裸流,采樣全是0错沽。

ffmpeg -lavfi anullsrc=r=44100:cl=mono -t 10 -f s16le -c:a pcm_s16le null-10s.raw

生成一段指定內(nèi)容的裸流(并不能設(shè)定為特定值簿晓,如果指定的是0,輸出的是0千埃,否則是最大值)憔儿。

ffmpeg -lavfi aevalsrc=1 -t 1 -f s16le -c:a pcm_s16le eval-1s.raw

采樣的數(shù)值含義

執(zhí)行如下命令,可以查看音頻文件的音量:

ffmpeg -i sine-10s.wav -filter:a volumedetect -f null /dev/null

獲得輸出內(nèi)容:

n_samples: 441000
mean_volume: -21.1 dB
max_volume: -18.1 dB
histogram_18db: 128000

看這個(gè)數(shù)據(jù)仍然不太明白音量到底是什么镰禾,通過看源碼,形成大體上的理解唱逢,0dB被當(dāng)作音量的極大值吴侦,對(duì)應(yīng)16位有符號(hào)數(shù)的最大值就是32767(0x8000),等于91dB的音量坞古。(目前并不確切知道為什么選91分貝這個(gè)值备韧,似乎是再高的值人就受不了。)

#define AMPLITUDE 4095 // 4095 0x0fff 是12bit的最大值(無符號(hào))

#define MAX_DB 91

// 0x0fff 4095
// 0x8000 32767

4095/32767 = 0.1249733

db = 20 * log10(0.1249733) = -18.1

參考

參考:http://ffmpeg.org/ffmpeg-filters.html#anullsrc

參考:http://ffmpeg.org/ffmpeg-filters.html#sine

參考:http://ffmpeg.org/ffmpeg-filters.html#aevalsrc

參考:https://trac.ffmpeg.org/wiki/AudioVolume

參考:http://ffmpeg.org/ffmpeg-filters.html#volumedetect

參考:https://stackoverflow.com/questions/2445756/how-can-i-calculate-audio-db-level

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痪枫,一起剝皮案震驚了整個(gè)濱河市织堂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奶陈,老刑警劉巖易阳,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吃粒,居然都是意外死亡潦俺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來事示,“玉大人早像,你說我怎么就攤上這事⌒ぞ簦” “怎么了卢鹦?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長劝堪。 經(jīng)常有香客問我冀自,道長,這世上最難降的妖魔是什么幅聘? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任凡纳,我火速辦了婚禮,結(jié)果婚禮上帝蒿,老公的妹妹穿的比我還像新娘荐糜。我一直安慰自己,他們只是感情好葛超,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布暴氏。 她就那樣靜靜地躺著,像睡著了一般绣张。 火紅的嫁衣襯著肌膚如雪答渔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天侥涵,我揣著相機(jī)與錄音沼撕,去河邊找鬼。 笑死芜飘,一個(gè)胖子當(dāng)著我的面吹牛务豺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嗦明,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼笼沥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了娶牌?” 一聲冷哼從身側(cè)響起奔浅,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诗良,沒想到半個(gè)月后汹桦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鉴裹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年营勤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灵嫌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡葛作,死狀恐怖寿羞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赂蠢,我是刑警寧澤绪穆,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站虱岂,受9級(jí)特大地震影響玖院,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜第岖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一难菌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔑滓,春花似錦郊酒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹄咖,卻和暖如春褐健,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背澜汤。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蚜迅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俊抵。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓谁不,卻偏偏與公主長得像,于是被迫代替她去往敵國和親务蝠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拍谐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355