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
天小編將分享前端開(kāi)發(fā)中必學(xué)的知識(shí)點(diǎn),HTML5中關(guān)于音視頻處理
基本內(nèi)容:目前國(guó)內(nèi)的視頻網(wǎng)站 - Flash技術(shù),HTML5的視頻處理首先替換Flash技術(shù),支持的視頻格式有:
1.MP4 - .mp4 目前比較主流的視頻格式。
2.OGG - .ogv 手機(jī)端的視頻格式。
3.WebM - 目前唯一一個(gè)支持超高清視頻格式,該視頻格式出自Goggle公司。
問(wèn): 如何處理視頻?
答:<video>元素 - 引入單個(gè)格式視頻文件,它由自己的屬性組成。 src屬性 - 指定視頻文件的地址, width屬性 - 設(shè)置視頻寬度, height屬性 - 設(shè)置視頻高度。語(yǔ)法規(guī)范:<video src="視頻文件路徑" width=“100px”>
!!需要注意的是:視頻的寬高比不會(huì)改變, 在video元素內(nèi)定義不支持的提示內(nèi)容。
如果要想在<video>元素引入多個(gè)格式視頻文件,那么就使用<source/>,使用這種方式能夠?qū)崿F(xiàn)各個(gè)瀏覽器的兼容性,語(yǔ)法規(guī)范:
<video>
<source src="視頻文件路徑1"/>
<source src="視頻文件路徑2"/>
<source src="視頻文件路徑3"/>
</video>
<video>元素的屬性
autoplay屬性 - 自動(dòng)播放
controls屬性 - 提供控制面板
loop屬性 - 循環(huán)播放
poster屬性 - 播放之前顯示一張圖片
preload屬性 - 預(yù)加載(視頻)
none - 不加載
auto - (默認(rèn)值)自動(dòng)(盡快加載完畢)
metadata - 只加載除視頻之外的信息(寬和高)
video的高級(jí)用法 方法
play() - 播放視頻
pause() - 暫停視頻
load() - 加載視頻
canPlayType() - 判斷是否支持該格式
事件
play - 播放視頻時(shí)觸發(fā)
pause - 暫停視頻時(shí)觸發(fā)
ended - 結(jié)束播放時(shí)觸發(fā)
error - 播放錯(cuò)誤時(shí)觸發(fā)
canplay - 可播放時(shí)觸發(fā)(不考慮整體)
canplaythrough - 整體播放順利時(shí)觸發(fā)
progress - 下載進(jìn)度
屬性
paused - 判斷視頻當(dāng)前是否暫停,如果暫停狀態(tài),返回true
ended - 判斷視頻當(dāng)前是否結(jié)束播放,如果結(jié)束播放,返回true
duration - 當(dāng)前視頻的總時(shí)長(zhǎng)
currentTime - 獲取或設(shè)置當(dāng)前視頻播放的位置
基本內(nèi)容:目前HTML頁(yè)面實(shí)現(xiàn)音頻處理,將Windows Media Player播放器,內(nèi)置頁(yè)面中,使用Flash技術(shù)實(shí)現(xiàn)音頻處理,HTML5實(shí)現(xiàn)音頻處理支持的音頻格式有:
1.mp3 - 感謝百度(MP3)
2.ogg
3.wav
問(wèn): 如何使用音頻?
答: audio元素 - 引入一種音頻格式。
<audio>元素的屬性
src屬性 - 引入音頻文件,作用 - 實(shí)現(xiàn)頁(yè)面背景音樂(lè)播放
audio元素 - 引入多種音頻格式
source元素
autoplay - 自動(dòng)播放
controls - 提供控制面板
loop - 循環(huán)播放
preload - 預(yù)加載
audio的高級(jí)用法
事件
play - 播放音頻時(shí)觸發(fā)
方法
play() - 播放音頻
pause() - 暫停音頻
屬性
paused - true,表示暫停狀態(tài)
!! 需要特別注意,IE 8及之前的版本都不支持
H5 視頻兼容性處理總結(jié):跨平臺(tái)視頻播放解決方案
**引言:H5視頻的重要性及挑戰(zhàn)**
隨著HTML5標(biāo)準(zhǔn)的發(fā)展和完善, `<video>` 標(biāo)簽已經(jīng)成為現(xiàn)代Web開(kāi)發(fā)中實(shí)現(xiàn)內(nèi)嵌視頻播放的重要手段。然而,不同瀏覽器和設(shè)備對(duì)HTML5視頻的支持程度存在差異,這就要求開(kāi)發(fā)者掌握一套行之有效的視頻兼容性處理策略,確保視頻在多種環(huán)境下流暢播放。本文將深入探討H5視頻兼容性的關(guān)鍵問(wèn)題,并分享實(shí)戰(zhàn)經(jīng)驗(yàn)與代碼示例。
---
### **一、視頻編碼格式與容器的選擇**
**標(biāo)題:了解MIME類型與視頻格式兼容性**
為了保證視頻在所有瀏覽器中都能正確播放,你需要考慮視頻編碼格式(如H.264、VP8/VP9)以及封裝容器(MP4、WebM、Ogg)的兼容性。
```html
<video width="320" height="240" controls>
<!-- MP4 for Safari, IE, and old Firefox versions -->
<source src="movie.mp4" type="video/mp4">
<!-- WebM for most modern browsers -->
<source src="movie.webm" type="video/webm">
<!-- Ogg for older Firefox versions -->
<source src="movie.ogg" type="video/ogg">
<!-- Fallback content for browsers that don't support the video tag -->
<p>您的瀏覽器不支持內(nèi)嵌視頻標(biāo)簽,請(qǐng)升級(jí)或更換瀏覽器。</p>
</video>
```
在上述代碼中,我們按照瀏覽器對(duì)視頻格式的支持優(yōu)先級(jí),依次提供了MP4、WebM和Ogg格式的視頻源文件。
---
### **二、自動(dòng)檢測(cè)與適配**
**標(biāo)題:JavaScript輔助實(shí)現(xiàn)智能切換**
通過(guò)JavaScript動(dòng)態(tài)檢測(cè)瀏覽器對(duì)不同視頻格式的支持情況,可以自動(dòng)調(diào)整播放源。
```javascript
var videoElement = document.querySelector('video');
var sources = [
{src: 'movie.mp4', type: 'video/mp4'},
{src: 'movie.webm', type: 'video/webm'},
{src: 'movie.ogg', type: 'video/ogg'}
];
sources.forEach(function(source) {
var sourceElement = document.createElement('source');
sourceElement.src = source.src;
sourceElement.type = source.type;
videoElement.appendChild(sourceElement);
});
// 檢測(cè)是否能播放第一個(gè)源,若不能則移除并嘗試下一個(gè)
function tryNextSource(video) {
if (video.paused && video.error) {
var nextSource = video.getElementsByTagName('source')[0];
if (nextSource) {
video.removeChild(nextSource);
tryNextSource(video);
}
}
}
videoElement.addEventListener('error', function() {
tryNextSource(this);
}, true);
// 開(kāi)始播放視頻
videoElement.load();
videoElement.play();
```
這段代碼會(huì)在遇到無(wú)法播放的視頻源時(shí),自動(dòng)切換至下一個(gè)可用的源。
---
### **三、響應(yīng)式設(shè)計(jì)與全屏控制**
**標(biāo)題:適應(yīng)不同屏幕尺寸與設(shè)備特性**
針對(duì)移動(dòng)端設(shè)備和桌面端的不同需求,視頻元素應(yīng)當(dāng)具有響應(yīng)式布局,并且提供全屏播放的功能。
```html
<video width="100%" height="auto" playsinline controls>
<!-- Video sources... -->
</video>
<script>
// 全屏控制
var video = document.querySelector('video');
if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.mozRequestFullScreen) { /* Firefox */
video.mozRequestFullScreen();
} else if (video.webkitRequestFullscreen) { /* Chrome, Safari & Opera */
video.webkitRequestFullscreen();
}
</script>
```
這里通過(guò)CSS設(shè)置寬度為100%,高度自適應(yīng)以實(shí)現(xiàn)響應(yīng)式布局,并利用瀏覽器的Fullscreen API來(lái)控制視頻全屏播放。
---
### **四、視頻加載優(yōu)化與錯(cuò)誤處理**
**標(biāo)題:提高加載速度與用戶體驗(yàn)**
對(duì)于大體積視頻,可采用預(yù)加載或緩沖技術(shù)改善用戶體驗(yàn)。
```html
<video preload="auto" poster="thumbnail.jpg" controls>
<!-- Video sources... -->
</video>
<script>
// 監(jiān)聽(tīng)視頻加載事件
video.addEventListener('loadedmetadata', function() {
console.log('視頻元數(shù)據(jù)已加載,可以獲取時(shí)長(zhǎng)等信息');
});
video.addEventListener('canplay', function() {
console.log('視頻可以開(kāi)始播放,但可能需要緩沖');
});
video.addEventListener('canplaythrough', function() {
console.log('視頻可以流暢播放,無(wú)需額外緩沖');
});
// 錯(cuò)誤處理
video.addEventListener('error', function(event) {
console.error('視頻加載失敗:', event.target.error.code);
});
</script>
```
通過(guò)設(shè)置preload屬性為"auto"可提前加載視頻資源,同時(shí)監(jiān)聽(tīng)不同的視頻加載狀態(tài)事件,以便更好地處理加載錯(cuò)誤和提升用戶體驗(yàn)。
---
**結(jié)語(yǔ):**
通過(guò)對(duì)H5視頻兼容性處理的深入探討,我們已了解了視頻編碼格式選擇、智能切換源、響應(yīng)式設(shè)計(jì)、全屏控制以及加載優(yōu)化等方面的關(guān)鍵技術(shù)。在實(shí)踐中靈活運(yùn)用這些策略,將有助于構(gòu)建出更加穩(wěn)定、高性能、跨平臺(tái)的Web視頻播放環(huán)境。持續(xù)關(guān)注瀏覽器發(fā)展趨勢(shì),及時(shí)更新視頻處理方案,方能在Web前端開(kāi)發(fā)領(lǐng)域始終保持領(lǐng)先優(yōu)勢(shì)。
html5 播放器默認(rèn)是可以下載視頻的,在默認(rèn)的控制器(給 video 標(biāo)簽添加 controls 屬性開(kāi)啟)上會(huì)有下載菜單, 即使不使用默認(rèn)提示的控制器,右鍵彈出的上下文菜單中也會(huì)有保存視頻的選項(xiàng)。
通過(guò) controlslist 屬性可以設(shè)置瀏覽器提供的控制器,不讓下載菜單顯示出來(lái)。controlslist 還可以設(shè)置不顯示全屏等功能同,但是瀏覽器 支持較差,尤其是移動(dòng)端瀏覽器。
<video src="test.mp4" playsinline autoplay="false" controls controlslist="nodownload"></video>
將 controlslist 的值設(shè)置為 nodownload ,就不會(huì)出現(xiàn)下載菜單了,不過(guò) PC 上點(diǎn)擊右鍵的上下文菜單的保存視頻選項(xiàng)仍然有用,還是很容易被下載。
如果是通過(guò)自定義樣式來(lái)控制播放暫時(shí)等操作的控制條,還可以將 video 禁右鍵或者蒙上一層 div 來(lái)阻止彈出上下文菜單,防止下載。
雖然通過(guò) controlslist 可以防止下載,但是有些瀏覽器不支持,很多移動(dòng)端的瀏覽器會(huì)直接接管播放器。 如果用戶懂一點(diǎn)技術(shù),捕獲視頻文件的鏈接,就可以直接打開(kāi)鏈接進(jìn)行下載了。 我們可以利用 Media Source Extensions API 來(lái)給文件做加密,這套技術(shù)本來(lái)是用于擴(kuò)展的,通過(guò)擴(kuò)展可以兼容更多 的視頻格式,可以認(rèn)為是前端的一套自定義轉(zhuǎn)碼的接口,將文件實(shí)時(shí)轉(zhuǎn)碼成瀏覽器支持的格式。
服務(wù)器端做好視頻的加密,將原視頻文件通過(guò)對(duì)稱性加密生成一個(gè)加密新文件,客戶端將加密的新文件加載后進(jìn)行解密, 然后將解密后的原文件內(nèi)容通過(guò) MediaSource 推送,完成視頻的播放。
<canvas height="240" width="320" id="player" onclick="playOrPause()"></canvas>
const video = document.getElementById('videoId')
// 視頻編碼譯碼器,使用工具 mp4info 可以查看
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
const mediaSource = new MediaSource()
video.src = URL.createObjectURL(mediaSource)
mediaSource.addEventListener('sourceopen', e => {
const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
// 請(qǐng)求加密文件,然后解密添加到 sourceBuffer,也可以將文件裁切成多個(gè)部分,分多次加載
fetch('./chunk')
.then(async resp => {
const blob = await resp.blob()
const buf = await blob.arrayBuffer()
sourceBuffer.addEventListener('updateend', () => {
// 如果是多個(gè)文件塊,可以在判定已經(jīng)添加完所有塊后結(jié)束(一般會(huì)搞個(gè)塊列表做比對(duì)的)
mediaSource.endOfStream()
})
// decode 是自定義的解碼函數(shù),將請(qǐng)求到的加密文件 chunk 內(nèi)容解密成為真正的 mp4 文件
// ,要與前面的 mimeCodec 對(duì)應(yīng),否則會(huì)有錯(cuò)誤
// 這個(gè)示例省略了很多錯(cuò)誤處理,要處理錯(cuò)誤需要對(duì) mediaSource 和 sourceBuffer 做 error 事件處理
sourceBuffer.appendBuffer(decode(buf))
console.log('appendBuffer after')
})
.catch(console.error)
})
這樣處理后,通過(guò)控制臺(tái) network 查看到的是加密文件的請(qǐng)求地址,拿到后也不能播放,查看 video 標(biāo)簽源地址是 生成的臨時(shí)地址,也無(wú)法直接打開(kāi)。并且,通過(guò) Media Source Extensions API 還可以實(shí)現(xiàn)視頻分塊做按需加載。 其實(shí) video 標(biāo)簽播放視頻也會(huì)自動(dòng)按需請(qǐng)求內(nèi)容(僅部分瀏覽器),需要服務(wù)器做好對(duì) Range 消息頭的支持,根據(jù)參數(shù)來(lái)返回部分文件內(nèi)容。 不過(guò) Media Source Extensions API 的兼容性不是很好,ie 和 safari 都是不支持的, 新版本 mac 上的 safari 不知道是否能支持。經(jīng)過(guò)測(cè)試,小部分移動(dòng)端瀏覽器也不支持,無(wú)法顯示出視頻,大部分移動(dòng)端瀏覽都可以支持的很好。 有些網(wǎng)站的播放器做了兼容,對(duì)于不支持 MSE 的瀏覽器仍然使用 video 標(biāo)簽播放原 mp4 文件。
基于 canvas 也是一種方案,好處是不會(huì)被瀏覽器識(shí)別成視頻,也就不會(huì)被接管。很多不太規(guī)范的移動(dòng)端瀏覽器 都是直接接管視頻播放器,自定義的播放器樣式完全沒(méi)用,不會(huì)被顯示出來(lái),使用 canvas 就可以解決這個(gè)問(wèn)題。
const canvas = document.getElementById('player')
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d')
const video = document.createElement('video')
video.addEventListener('canplay', e => {
// 渲染封面
this.renderCover()
})
fetch('./test.mp4')
.then(async resp => {
const blob = await resp.blob()
video.src = URL.createObjectURL(blob)
})
.catch(console.error)
function playOrPause() {
if (video.ended) {
return
}
if (video.paused) {
video.play()
startRender()
} else {
video.pause()
}
}
function startRender() {
requestAnimationFrame(() => {
renderVideo()
if (!video.paused && !video.ended) {
startRender()
}
})
}
function renderCover() {
ctx.clearRect(0, 0, 320, 240)
ctx.fillStyle = '#000000'
ctx.fillRect(0, 0, 320, 240)
ctx.font = '40px Arial'
ctx.fillStyle = '#ffffff'
const text = '點(diǎn)擊播放'
const m = ctx.measureText(text)
ctx.fillText(text, 320 / 2 - m.width / 2, 240 / 2 + 40 / 2)
}
function renderVideo() {
ctx.clearRect(0, 0, 320, 240)
ctx.drawImage(video, 0, 0, 320, 240)
if (video.paused) {
ctx.font = '40px Arial'
ctx.fillStyle = '#ffffff'
const text = '已暫停'
const m = ctx.measureText(text)
ctx.fillText(text, 320 / 2 - m.width / 2, 240 / 2 + 40 / 2)
}
}
以上僅僅是非常簡(jiǎn)單的 demo,這個(gè)方案真要完善工作量還是挺大的,除操作條和字幕功能外,視頻全屏還需要做一定的重新渲染處理, 有些瀏覽器還不支持全屏 API (requestFullscreen),導(dǎo)致沒(méi)有辦法將視頻全屏展示。 即便如此,也無(wú)法保證百分百不能被下載, 有些瀏覽器還有媒體嗅探功能,當(dāng)請(qǐng)求了媒體文件后,就會(huì)被檢測(cè)到,提示用戶檢測(cè)到有媒體文件, 詢問(wèn)用戶是否要下載。
經(jīng)過(guò)我對(duì)某個(gè)移動(dòng)端瀏覽器的測(cè)試,改 content-type 和后綴名也不行,只要請(qǐng)求的是視頻文件就會(huì)被檢測(cè)到。 只有把文件加密,請(qǐng)求的是加密文件,不是真正的視頻文件,這樣就不能被檢測(cè)到了,然后客戶端解密后再播放。
實(shí)測(cè)這個(gè)方案兼容性也不是很好,部分移動(dòng)端瀏覽器會(huì)渲染不出來(lái)視頻內(nèi)容,有些還會(huì)出現(xiàn)卡頓和圖像錯(cuò)亂。不過(guò)微信內(nèi)置 以及火狐等一些較為先進(jìn)的移動(dòng)端瀏覽器支持的都比較好。不過(guò),使用了 canvas 方案就沒(méi)有一些原生功能的支持的,如 小窗播放(畫(huà)中畫(huà)模式)。
經(jīng)過(guò)我的測(cè)試,對(duì) MSE 和 canvas 方案無(wú)法支持的瀏覽器,恰恰是一些以下載視頻為特色的移動(dòng)端瀏覽器, 這些瀏覽器內(nèi)核可能也比較舊,或者是因?yàn)樾薷膬?nèi)核導(dǎo)致的不兼容,不考慮這些瀏覽器 MSE 應(yīng)該是最佳方案, 因?yàn)?MSE 可以實(shí)現(xiàn)按需漸近加載視頻。
由于視頻本身就非常耗資源,即時(shí)加密對(duì)服務(wù)器要求高,最好是先加密好。 加密必須是對(duì)稱性的,能加密也能解密,通過(guò)破解前端代碼掌握解密方法,仍然有辦法解開(kāi)視頻內(nèi)容。 如果視頻是提前加密好再存儲(chǔ)的,也不好去搞動(dòng)態(tài)密鑰。
html5 視頻播放器想要下載并做好兼容是非常困難的,基本上不太可能。有些對(duì)版權(quán)保護(hù)比較嚴(yán)格的網(wǎng)站,采取了 只能使用客戶端看視頻的方案,體驗(yàn)上就差一些了。比如 cctalk 這個(gè)平臺(tái),視頻作者可以設(shè)置保護(hù),對(duì)于需要保護(hù)的 視頻只能通過(guò)客戶端觀看,其它的視頻仍然可以網(wǎng)頁(yè)上直接播放。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。