Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
.MP4解析工具
mediainfo
mp4box:http://download.tsi.telecom-paristech.fr/gpac/mp4box.js/filereader.html
對于Mp4來說,都是一個個box來去組織元素。比如豎著的box,就是一個個box,這里就是重點關注moov。mp4?件由box組成,每個box分為Header和Data。其中Header部分包含了box的類型和??,Data包含了?box或者數據,box可以嵌套?box。MP4?件的基本組成單元是box,也就是說MP4?件是由各種各樣的box組成的,有parent box,還有children box。因此,這些boxes之間存在?定的層次關系,總結如下表所示,表中標記出了各個box必選或可選特性,√代表Box必選。
下圖是?個典型mp4?件的基本結構:
Hexinator:
Mp4box和mediainfo對比。
這個trak,就是表示是多少路音頻和視頻。每一個AVstream都對應一個track。每個track,可能都有寬高信息,編譯器信息,采樣率,聲道,time_base(time_scale)。
表示track width和heigth使用了4個字節。
視頻和音頻的時間刻度不一樣。
音視頻的handler也不一樣。
比較重要的sample table。
一個MP4文件分為多個track,一個track分為多個chunk,一個chunk有多個sample。mp4數據索引和真正的數據分開區域存儲。
先用數據索引找到moov,然后才能找到mdat。
下面的解釋就是chunk1-84,都是一一對應1個sample,chunk85,一一對應2個sample,chunk86-88,一一對應一個sample,chunk89,一一對應2個sample,chunk90,一一對應一個sample。
可以根據sample size去讀取每一幀數據的大小。
ftyp
File Type Box,?般在?件的開始位置,描述的?件的版本、兼容協議等。
moov
Movie Box,包含本?件中所有媒體數據的宏觀描述信息以及每路媒體軌道的具體信息。?般位于放在?件末尾,但如果為了?持http邊下載邊播放則需要將moov提前。注意,當改變moov位置時,內部?些值需要重新計算。
mdat
Media Data Box,存放具體的媒體數據。
Moov Insider
mp4的媒體數據信息主要存放在Moov Box中,是我們需要分析的重點。moov的主要組成部分如下:
mvhd
Movie Header Box,記錄整個媒體?件的描述信息,如創建時間、修改時間、時間度量標尺、可播放時?等。
下圖示例中,可以獲取?件信息如時?為 Duration: 5016 ms秒。
udta
User Data Box,?定義數據。
track
Track Box,記錄媒體流信息,?件中可以存在?個或多個track,它們之間是相互獨?的。
每個track包含以下?個組成部分:
tkhd
Track Header Box,包含關于媒體流的頭信息。下圖示例中,可以看到流信息如視頻流寬度800,?度1920。
?頻的tkhd,則?如duration、volume等。
mdia
Media Box,這是?個包含track媒體數據信息的container box。?box包括:
mdhd:Media Header Box,存放視頻流創建時間,?度等信息。
hdlr:Handler Reference Box,媒體的播放過程信息。
minf:Media Information Box,解釋track媒體數據的handler-specific信息。minf同樣是個containerbox,其內部需要關注的內容是stbl,這也是moov中最復雜的部分。stbl包含了媒體流每?個sample在?件中的offset,pts,duration等信息。想要播放?個mp4?件,必須根據stbl正確找到每個sample并送給解碼器。
mdia展開如下圖所示:
mdhd
Media Header Box,存放視頻流創建時間,?度等信息。視頻的mdhd,Time scale,Duration等信息。
?頻的mdhd,也類似視頻,但要注意Time scale,我們在計算時間戳的時候都要使?該Time scale,對應我們流??的AVStream->time_base。
hdlr
Handler Reference Box,媒體的播放過程信息。視頻的hdlr,重點Component subtype: vide。
?頻的hdlr,Component subtype: soun,如果我們多個?軌的時候,Component name:粵語。
我們分析的?件另?路?軌,根據不同的名字來進行區別。
minf
minf:Media Information Box,解釋track媒體數據的handler-specific信息。minf同樣是個containerbox,其內部需要關注的內容是stbl,這也是moov中最復雜的部分。stbl包含了媒體流每?個sample在?件中的offset,pts,duration等信息。想要播放?個mp4?件,必須根據stbl正確找到每個sample并送給解碼器。
?且需要注意的是,minf??的?容器,?頻和視頻軌是有區別的,?如視頻軌:vmhd, ?頻軌則為:smhd
vmhd
smhd
Stbl Insider
Sample Table Box,上?提到mdia中最主要的部分是存放?件中每個sample信息的stbl。在解析stbl前,我們需要區分chunk和sample這兩個概念。
在mp4?件中,sample是?個媒體流的基本單元,例如視頻流的?個sample代表實際的nal數據。chunk是數據存儲的基本單位,它是?系列sample數據的集合,?個chunk中可以包含?個或多的sample。
stbl?來描述每個sample的信息,包含以下?個主要的?box:
stsd
Sample Description Box,存放解碼必須的描述信息。下圖示例中,對于h264的視頻流,其具體類型為 avc1 ,extensions中其中存放有sps,pps等解碼必要信息。
視頻的stsd
??包含了avc1,avc1???包含了avcC和pasp。
avc1:包含了視頻Width、Height。
avcC:包含了視頻編碼器相關的信息,包括sps、pps等信息。
?頻的stsd
用Hexinator分析,包含了音頻相關的信息,比如采樣率,通道數。
stts
Time-to-Sample Box,定義每個sample時?。Time-To-Sample的table entry布局如下:
stts table entry布局
sample count:sample個數。
sample duration:sample持續時間。
持續時間相同的連續sample可以放到?個entry?達到節省空間的?的。這?先給出來的是視頻的stts,Number of entries,這個參數需要注意并不是sample的個數,sample的實際數量需要將每個entry的sample count進?累加才是真正的sample個數。
下圖示例中,第1個sample時間為3720,單位?mdhd的time scale進?換算,?如視頻的是90000,此時換算成秒為3720/90000 = 0.0413333333333333秒。
再給出個?頻的stts,只是mdhd的time scale的差別,之前我們看到?頻為44100,則計算第?個sample的時間。1024/44100=0.0232199546485261秒。
stss
Sync Sample Box,同步sample表,存放關鍵幀列表,關鍵幀是為了?持隨機訪問。
stss的table entry布局如下:
stss table entry布局
下圖示例中,該視頻track有3個關鍵幀:
stsc
Sample-To-Chunk Box,sample-chunk映射表。
上?提到mp4通常把sample封裝到chunk中,?個chunk可能會包含?個或者?個sample。Sample-To-Chunk Atom的table entry布局如下圖所示:
First chunk:使?該表項的第?個chunk序號
Samples per chunk:使?該表項的chunk中包含有?個sample
Sample description ID:使?該表項的chunk參考的stsd表項序號
下圖示例中,可以看到該視頻track?共有1個stsc表項,chunk序列1-x,每個chunk包含?個sample。這?則說明每個chunk??只有?個sample(?個chunk是可以有多個sample)。
stsz
Sample Size Box,指定了每個sample的size。Sample Size Atom包含兩sample總數和?張包含了每個sample size的表。
sample size 表的entry布局如下圖:
下圖示例中,該視頻流?共有110個sample,第1個sample??為42072字節,第2個sample??為7354個字節。
stco
Chunk Offset Box,指定了每個chunk在?件中的位置,這個表是確定每個sample在?件中位置的關鍵。該表包含了chunk個數和?個包含每個chunk在?件中偏移位置的表。每個表項的內存布局如下:
需要注意,這?stco只是指定的每個chunk在?件中的偏移位置,并沒有給出每個sample在?件中的偏移。想要獲得每個sample的偏移位置,需要結合 Sample Size box(stsz)和Sample-To-Chunk(stsc) 計算后取得。
下圖示例中,該視頻流第1個chunk在?件中的偏移為4750,?這?是每個chunk只有?個sample,此時第?個sample的起始位置就為4750->0x1D78,數據??則參照stsz,第?個sample size為172818。
?如偏移位置,7544->0x1D78。
如何計算sample偏移位置
上?提到通過stco并不能直接獲取某個sample的偏移位置,下?舉例說明如何獲取某?個pts對應的sample在?件中的位置。
?體需要以下步驟:
(1)將pts轉換到媒體對應的時間坐標系。
(2)根據stts((decoding) time-to-sample)計算某個pts對應的sample序號。
(3)根據stsc(sample-to-chunk)計算sample序號存放在哪個chunk中。
(4)根據stco(chunk offset)獲取對應chunk在?件中的偏移位置。
(5)根據stsz獲取sample在chunk內的偏移位置并加上第4步獲取的偏移,計算出sample在?件中的偏移。
例如,想要獲取3.64秒視頻sample數據在?件中的位置。
(1)根據time scale參數,將3.64秒轉換為視頻時間軸對應的3640000 (假如時間刻度不為毫秒)。
視頻軌:time scale為90000,轉成對應的時間戳為3.64秒*90000。
(2)遍歷累加下表所示stts所有項?,計算得到3640000位于第110個sample = 327600。
(3)計算出多個sample_deltas疊加才到了327600, 我們這?姑且按3780作為平均值計算,實際是3720*1+3780*1+3690*1+3780*2 ...... 這樣?直疊加進?。327600/3780 =86.66666666666667,取整為86。
(4)查詢下表所示stsc所有項?,計算得到第86個sample位于第86個chunk,并且在該chunk中位于第1個sample(因為我們的碼流是每個chunk對應了?個sample)。
(5)查詢下表所示stco所有項?,得到第86個chunk在?件中偏移位置為1004678。使?hexinator。
(6)查詢下表所示stsz所有項?,得到第86個sample的size為20934。計算得到3.64秒視頻sample數據在?件中。
offset:1004678+0 = 1004678
size:20934。
驗證:?編輯器打開mp4?件,定位到?件偏移1004678位置。09分隔符,這?占?了6個字節, 再看真正的數據區域,前4字節也為 NALU的?度0x000051bc=20924。
總共占?的字節計算 4+2+4+20924 = 20934。
《整理mp4協議重點,將協議讀薄》:
?個chunk含有多個sample的情景參考下?鏈接進?分析:
mp4?件格式重點解析:https://www.jianshu.com/p/44c9567d8fcb
本篇文章就分析到這里,非常詳細的MP4分析,如果對你有用,可以關注,點贊,收藏,轉發。
在剛接觸 p5.js 時我以為這只是一個藝術方向的 canvas 庫,沒想到它還支持視頻文件和視頻流的播放。
本文簡單講講如何使用 P5.js 播放視頻。
p5.js 除了可以使用 video 元素播放視頻外,還支持使用 image 控件播放視頻。
p5.js 的 createVideo() 方法可以創建一個 <video> 元素。
createVideo(src, [callback]) 可以傳入2個參數:
錄制 GIF 后比較卡,將就看著吧~
// 加載本地視頻
let playing = false // 播放狀態
let video = null // 視頻
let button = null // 按鈕
// 視頻加載完成的回調函數
function afterLoad() {
console.log('加載完成')
}
// 加載資源的生命周期
function preload() {
video = createVideo('assets/02.mp4', afterLoad)
}
// 初始化的生命周期
function setup() {
noCanvas()
button = createButton('播放')
button.mousePressed(toggleVid)
}
// 點擊按鈕的事件
function toggleVid() {
if (playing) {
video.pause()
button.html('播放')
} else {
video.loop()
button.html('暫停')
}
playing = !playing;
}
粗略講講上面這段代碼。
除了 video.loop() 方法,還可以使用 video.play() 播放視頻。loop 是循環播放;play 只播放一次,播完就暫停。
createVideo() 方法的第一個參數除了傳入一個字符串類型的視頻地址外,還可以傳入字符串數組,作用就是兼容處理。
比如你的視頻資源只有 2.mp4,你希望可以先播放 1.mp4,沒有這個視頻再播放 2.mp4,就可以這樣寫:
createVideo(['1.mp4', '2.mp4'])
但通常我們不會這樣寫,通常我們會給同一個視頻提供不同的視頻格式,然后用這種方法傳入多個視頻地址。
因為有些瀏覽器不一定支持你想播放的地址,此時就可以做個保底處理。
使用 createVideo() 方法創建完視頻后,可以通過 size(width, height) 設置視頻的寬高。
let video = null
function preload() {
video = createVideo('assets/02.mp4')
video.size(300, 600)
}
使用 createVideo() 創建的視頻控件可以使用 volume() 設置視頻的音量,該方法接受1個參數,參數值在 0~1 之間。
let video = null
function preload() {
video = createVideo('assets/02.mp4', videoLoaded)
}
function videoLoaded() {
video.volume(0.5) // 將視頻音量設置為50%
}
一開始我也沒想到 image 控件可以播放視頻,誤打誤撞試出來的。
這次我就不錄屏了,工友們自己運行試試看吧。
let playing = false
let video = null
let button = null
function preload() {
video = createVideo('assets/02.mp4')
}
function setup() {
video.hide()
createCanvas(568, 320)
button = createButton('播放')
button.mousePressed(toggleVid)
}
function draw() {
image(video, 0, 0)
}
function toggleVid() {
if (playing) {
video.pause();
button.html('播放');
} else {
video.loop();
button.html('暫停');
}
playing = !playing;
}
上面的代碼中,我在 setup() 里使用了 video.hide() 方法將 createVideo() 創建出來的 <video> 元素隱藏起來,因為這次我們需要將視頻渲染到畫布中,所以不再需要 <video> 了。
接著我們在 draw() 里用 image 不斷刷新視頻,所以上面這樣寫是對的。
其他地方沒變化。
如果你的設備有攝像頭,p5.js 是支持調用攝像頭并將內容展示在畫布上的。
let capture
function setup() {
createCanvas(480, 360)
capture = createCapture(VIDEO)
capture.hide()
}
function draw() {
image(capture, 0, 0, capture.width, capture.height)
}
通過 createCapture() 方法創建一個包含攝像頭的音頻/視頻源 <video> 元素,把這個元素的內容放在 p5.js 的 image 控件里。
這個默認是顯示的,而且它是一個獨立的元素,默認和畫布分離。所以使用 capture.hide() 方法把 <video> 元素隱藏起來,不然頁面中會出現兩個視頻窗口。
其他做法和前面的【方式2】差不多,這里就不再啰嗦了。
《p5.js 光速入門》
《p5.js 使用npm安裝p5.js后如何使用?》
《p5.js 變換操作》
《p5.js 3D圖形-立方體》
《p5.js 開發點彩畫派的繪畫工具》
《p5.js畫布操作實戰:創建,綁定指定元素,動態調整大小,隱藏滾動條,刪除畫布》
點贊 + 關注 + 收藏 = 學會了
網頁中添加視頻、聲音、動畫等,可以增強用戶體驗。在HTML5之前,為網頁添加多媒體的唯一辦法,就是使用第三方的插件(如,Adobe Flash等)。
HTML5中,提供了對多媒體的原生支持,只需通過 video 元素,就可以向網頁嵌入視頻、電影或音頻資源,通過 audio 元素向網頁嵌入音頻資源,省時省力。
HTML中嵌入視頻和音頻代碼
在HTML5時代,在網頁中嵌入視頻非常簡單,只需要一個 video 元素,并設置它的 src 屬性,使其鏈接一個視頻地址就可以完全搞定了,這個太esay了
<video src="media/vedio.mp4"></video>
把這個網站在IE8中打開一看,網站上除了一片空白外,什么也沒有,這是為什么呢?
原來 video 是HTML5最新引入的元素,并不是所有瀏覽器都支持它,IE8及以下版本都無法識別 video 標簽。如果瀏覽器不識別 video標簽,則會忽略它,當做什么都沒有。這就是網站上一片空白的原因。
這個問題好解決,只需在 video 標簽之間放置文本信息,不支持 video 標簽的老瀏覽器,會顯示 video 標簽之間的文本信息,以提示用戶瀏覽器不支持 video,就這么簡單!
<video src="media/vedio.mp4">
你的瀏覽器已經老掉牙了,不支持video,還不趕快使用現代瀏覽器O(∩_∩)O~!
</video>
在IE8上打開一看,確實顯示了提示文本,這下好多了,至少用戶知道自己的瀏覽器不能播放視頻,該換瀏覽器了。
下載了Opera瀏覽器的最新版本25.0,打開一看,怎么還是一片空白外!Opera瀏覽器明明是支持video標簽的,那又是為什么呢?
這個就得從視頻的編碼格式說起了。video 元素支持三種視頻格式:Ogg、MP4、WebM。
Ogg是帶有Theora視頻編碼和Vorbis音頻編碼的文件,后綴名為 .ogg;MP4是帶有H.264視頻編碼和AAC音頻編碼的MP4文件,后綴名為 .mp4;WebM是VP8視頻編碼和Vorbis音頻編碼的文件,后綴名為 .webm。
這個Opera瀏覽器呢,它可以支持ogg,但不支持mp4。由于Opera支持video標簽,故video標簽之間的文本信息沒有顯示出來,但它不支持ogg,所以就不進行播放,最終導致頁面出現一片空白。這下可怎么辦呢?
其實辦法有的是,我們可以從網上下載一副圖像,放到視頻播放窗口,如果視頻無法播放,就顯示這張圖片,是不是更好呢?從網上下載一張美女圖片,干脆叫beauty.jpg吧。那這個圖像怎么添加到視頻窗口呢?
video標簽有個poster 屬性,就是專門在視頻窗口放置圖片的。poster是一個video的占位符,無論什么情況下,只要視頻還沒有播放(視頻下載過程中、視頻不存在、不支持該視頻類型、用戶點擊播放按鈕前),就會顯示該圖像,可以看做是視頻播放之前插入的宣傳畫或海報。
<video src="media/vedio.mp4" poster = "img/beauty.jpg">
你的瀏覽器已經老掉牙了,不支持video,還不趕快使用現代瀏覽器O(∩_∩)O~!
</video>
在Opera瀏覽器上刷新一下,真的有一個美女沖著自己微笑呢。雖然視頻沒有播放出來,這回心情卻是好多了。
那我可不能一天到晚只看美女呀,視頻還是還是要想辦法播放出來的。既然Opera瀏覽器不支持mp4,我們就換成需要ogg吧,這樣就肯定沒問題了。
我想了想,這個辦法不好,萬一某個瀏覽器只支持支持ogg,不支持mp4呢。這年頭,什么都缺,就是不缺點子,隨便在網上一搜,辦法就有了。
在 video 元素中添加 source 元素,就可以解決這個問題。在source 元素中,通過 src 屬性指定視頻的地址,通過 type 屬性指定視頻的類型,以幫助瀏覽器決定是否能播放該視頻。并且,在 video 元素中可以添加任意多個source 元素,讓不同的 source 元素鏈接到不同的視頻文件。
這樣的話,當瀏覽器發現 video 元素時,首先會查看它本身是否定義了 src 屬性。如果沒有,就會檢查 source 元素。瀏覽器會逐個查看這些視頻源,直到找到一個可以播放的視頻。一旦找到,就會播放它并忽略其他的視頻源。我們干脆添加兩個source,一個是mp4,一個是ogg,這下視頻是一定能播放出來了。
<video poster = "img/beauty.jpg">
<source src="media/vedio.mp4" type="video/mp4">
<source src="media/vedio.ogg" type="video/ogg">
你的瀏覽器已經老掉牙了,不支持video,還不趕快使用現代瀏覽器O(∩_∩)O~!
</video>
在Opera瀏覽器上又刷新一下,只有美女沖著我微笑,視頻還是沒播放出來。唉,太粗心了,忘記添加播放視頻的控件了。
在video標簽中,通過添加controls 屬性來為視頻添加播放控件,方便用戶執行播放、暫停操作和音量控制。
<video poster = "img/beauty.jpg" controls>
(此處略去500字…)
</video>
在Opera瀏覽器上又刷新一下,效果真的不一樣,這次不僅看到美女,還看到了視頻控件。用鼠標猛戳一下那個播放按鈕,哈哈,不錯,真的聽到美妙的旋律。我們的ogg文件,終于播放出來了,讓我們好好享受一下吧O(∩_∩)O。
聽了一會,忽然一想,不對呀,我剛才點了播放按鈕后,等了半天才聽到聲音。能不能我一點播放按鈕,就立即播放呢?
原來視頻也是需要下載緩存的,點擊播放按鈕后,首先緩存,然后才播放的。那能不能在頁面加載的同時就緩存呢。這樣,用戶點擊播放后,就不必等待了。
這當然可以,在video標簽中,通過添加preload屬性來為視頻添加預加載功能,在頁面加載的同時加載視頻。
<video poster = "img/beauty.jpg" controls preload>
(此處略去500字…)
</video>
關于 preload 屬性,稍微再啰嗦一點,就是可以把它設置為 metadata,讓瀏覽器僅僅預加載視頻的基本信息,如尺寸、時長、以及一些關鍵的幀。這樣的話,在開始播放之前,瀏覽器可以提前計算視頻的顯示尺寸。
既然一切都OK了!讓我們看看mp4是不是能正常播放。下載最新版的Google Chrome 38.0瀏覽器,打開網頁,猛戳一下播放按鈕。
等等~,等等~,不對,怎么只有聲音沒有畫面,明明是mp4格式的文件呀?使用暴風影音試了一下,是有畫面的呀!
辛辛苦苦又在網上搜了一番,花了整整586秒,終于找到了答案。mp4視頻需要h.264編碼格式才會有圖像的。
找了一個 h.264 編碼格式的 mp4 試了一下,不錯,確實有圖像了!看了半天,原來是一部老外的電影,嘰里咕嚕一陣,一句話也沒聽懂。那O(∩_∩)O~,能否提供中文字幕呢,這樣就不必費老大勁去聽了!
HTML5中,通過在video元素添加track元素為視頻添加字幕。字幕文件有兩種格式:WebVTT和TTML。WebVTT是Web視頻文本軌跡(Web Video Text Track),是UTF-8編碼格式的文本文件;TTML是時序文本標記語言(Timed Text Markup Language),是XML格式的文件。兩種文件的具體格式,已經超出我們的討論范圍。
video元素支持添加多個track元素,不同的track元素鏈接到不同的字幕文件。用戶可以在各個字幕間進行切換。
<video poster = "img/beauty.jpg" controls preload>
<track src="en_track.vtt" kind="subtitles" srclang="en" label="English" default>
<track src="cn_track.vtt" kind="captions" srclang="zh" label="簡體中文">
</video>
track元素中,src屬性指定字幕文件的URL;srclang屬性字幕文件的語言類型,若kind 屬性值是 "subtitles" 時,該屬性必需的;label 屬性指定字幕標簽,每個字幕元素必需設置一個唯一不重復的標簽,切換字幕時,會顯示標簽的名稱;kind指定字幕內容類型,只能是subtitles、captions、descriptions、chapters、metadata 之一;default屬性指定是否是默認字幕,如果一個都沒指定,將不會自動顯示字幕。
除了字幕外,我還希望對視頻進行過多的控制,比如讓視頻自動播放、循環播放、默認靜音,以及視頻窗口的尺寸等等,這些都能做到嗎?
這已經不是什么事了,video 元素已經提供了相關屬性,根據需要設置相應的屬性就可以了。這些屬性及含義見表 23:
HTML中嵌入視頻和音頻代碼
哦,原來這么簡單呀!那就到此為止吧,網頁中嵌入視頻的全部代碼都在這里,就打包給你吧!
<video width="300" poster="img/beauty.jpg" controls preload autoplay loop muted>
<source src="media/vedio.mp4">
<source src="media/vedio.ogg">
<track src="en_track.vtt" kind="subtitles" srclang="en" label="English" default>
<track src="cn_track.vtt" kind="captions" srclang="zh" label="簡體中文">
你的瀏覽器已經老掉牙了,不支持video,還不趕快使用現代瀏覽器O(∩_∩)O~!
</video>
睜大眼睛一看,卻只有7行代碼。然而,就這區區7行代碼,可把他折磨得夠嗆。
看著這一切都全部搞定,他仰望著天空,長長呼了一口氣,顯得是那么的放松,那么的愜意。此時,他閉上眼睛,在自己的夢幻世界里遨游!
有了在網頁中嵌入視頻的經歷,要在網頁中嵌入音頻,那簡直就是小菜一碟了。只要把vedio元素換成 audio 元素,就全部搞定。
但需要了解的是,audio 所支持的音頻格式只有Ogg Vorbis、mp3 和 wav。還要知道,由于音頻沒有畫面,也就沒有 width、height、poster 屬性,而其他屬性都支持,并且跟視頻的含義相同。
網頁中嵌入音頻的代碼如下:
<audio controls preload autoplay loop muted>
<source src="media/audio.mp3">
<source src="media/audio.wav">
<source src="media/audio.ogg">
你的瀏覽器已經老掉牙了,不支持audio,還不趕快使用現代瀏覽器O(∩_∩)O~!
</audio>
*請認真填寫需求信息,我們會在24小時內與您取得聯系。