瀏覽器中視頻播放器實(shí)現(xiàn)的基本思路與代碼
前言
自定義個(gè)播放器,組件都是用的原生的,所以有點(diǎn)丑,重點(diǎn)關(guān)注業(yè)務(wù)邏輯吧。
界面大概長(zhǎng)下面這個(gè)樣子。
大家可以看著界面,在腦海中想一下自己會(huì)如何實(shí)現(xiàn)這個(gè)視頻播放器??梢詥?wèn)自己以下幾個(gè)問(wèn)題:
- 這個(gè)組件會(huì)接受那些props
- 如何獲取視頻的基本信息,包括時(shí)長(zhǎng),分辨率等
- 暫停、播放如何實(shí)現(xiàn)
- 拖動(dòng)進(jìn)度條的邏輯如何實(shí)現(xiàn)
- 視頻初始加載顯示loading如何處理
- 視頻播放過(guò)程中卡頓顯示loading如何處理
瀏覽器中的音視頻知識(shí)總結(jié)
視頻編碼
視頻,其實(shí)就是一系列連續(xù)播放的圖片,如果1s鐘播放24張圖片,視頻的幀率就是24。
如果視頻的的尺寸是1920*1080,即一張圖片的尺寸是1920*1080*3 bytes,乘3是因?yàn)橐粋€(gè)像素點(diǎn)3個(gè)比特,分別存放rbg,那么一個(gè)30分鐘的視頻所需要的存儲(chǔ)空間如下:
//1s視頻需要的存儲(chǔ)空間為: 1920*1080*3*24 bytes //30min視頻需要的存儲(chǔ)空間: 1920*1080*3*24 * 60*30=250.28GB
可以看到,非常大,所以視頻需要壓縮,于是就有了編碼(codec)的概念。視頻的編碼格式可以理解為壓縮格式,不同的編碼格式壓縮率不同,常見(jiàn)的編碼格式有 h264,mpeg4,vp8等。
此外,需要注意的一點(diǎn)是,因?yàn)榫幋a格式是有版權(quán)問(wèn)題的,所以不同的瀏覽器支持的編碼格式不同,所以就會(huì)出現(xiàn)有些編碼格式的視頻在某些瀏覽器播放不了,或者只有聲音沒(méi)有畫(huà)面的情況。
我們前端開(kāi)發(fā)只需要記住一點(diǎn),主流瀏覽器支持的視頻編碼格式是h264。
封裝格式
一個(gè)視頻文件內(nèi)會(huì)包含視頻流和音頻流,還有一些元數(shù)據(jù),例如分辨率信息,標(biāo)題等,這個(gè)文件的格式我們稱(chēng)為封裝格式,可以理解為打包格式,常見(jiàn)的mp4,webp,mov,mpeg等都是封裝格式。
封裝格式往往是與視頻編碼無(wú)關(guān)的,一個(gè)mp4文件,里面的視頻流編碼可以是h264,也可以是mpeg,所以就會(huì)出現(xiàn),同樣都是mp4文件,有的瀏覽器可以放,有的瀏覽器就放不了的問(wèn)題。
音視頻標(biāo)簽
<video controls poster="1.jpg" src="1.mp4" loop muted></video> <audio controls src="1.mp3"></audio>
src指定資源地址,poster為視頻指定一張封面圖,controls表示瀏覽器應(yīng)該顯示UI控件(每個(gè)瀏覽器樣式不同)
常用屬性
下面是video和audio的通用屬性

常用事件
video和audio通用事件

常用方法
- play() 控制視頻開(kāi)始播放
- pause() 控制視頻暫停播放
有了上述的屬性、事件及方法,我們就可以做很多事了,比如自定義播放器,使用播放器本地預(yù)覽視頻等。
整體思路如下
- 該組件接收一個(gè)視頻的src作為參數(shù)
- 監(jiān)聽(tīng)onLoadedMetadata事件,獲取視頻時(shí)長(zhǎng)(duration),真實(shí)寬高(videoWidth,videoHeight)
- 點(diǎn)擊播放/暫停時(shí),調(diào)用視頻元素的play/pause方法
- 播放時(shí),監(jiān)聽(tīng)onTimeUpdate,獲取當(dāng)前播放時(shí)間(currentTime),計(jì)算出進(jìn)度條的進(jìn)度
- 拖動(dòng)進(jìn)度條,設(shè)置視頻當(dāng)前播放時(shí)間,與步驟4相反
- 視頻初始加載時(shí),顯示loading。即組件初次渲染時(shí),loading屬性默認(rèn)為true,即顯示加載效果,當(dāng)視頻元數(shù)據(jù)加載時(shí),取消loading
- 視頻卡頓時(shí),顯示loading。該功能的實(shí)現(xiàn)是監(jiān)聽(tīng)的onWaiting事件,不卡頓時(shí),取消loading,監(jiān)聽(tīng)的是onCanPlay事件
代碼實(shí)現(xiàn)
代碼是用React實(shí)現(xiàn)的,用Vue也是一樣的,關(guān)注業(yè)務(wù)邏輯即可。如果大家有需求,我可以再更新下這篇文章,添加上Vue的代碼。
注意:dom原生事件在react中需要前面加個(gè)on,然后寫(xiě)成駝峰的形式
function formatDuration(duration) {
var sec_num = parseInt(duration, 10); // don't forget the second param
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours+':'+minutes+':'+seconds;
}
import React, { createRef, useState } from 'react'
import './VideoPlayer.css'
function VideoPlayer({src}){
const videoDom=createRef()
// 視頻當(dāng)前播放時(shí)間
const [curTime,setCurTime]=useState(0)
// 視頻時(shí)長(zhǎng)
const [duration,setDuration]=useState(0)
// 視頻狀態(tài),是否暫停
const [isPause,setPause]=useState(true)
// 視頻真是尺寸
const [size,setSize]=useState({width:1920,height:1080})
// 視頻加載中
const [waiting,setWaiting]=useState(true)
// 視頻元數(shù)據(jù)加載成功
const onLoad=(e)=>{
const {duration,videoWidth,videoHeight}=e.target
setDuration(duration)
setSize({width:videoWidth,height:videoHeight})
setWaiting(false)
}
// 控制播放暫停
const handlePlay=(play)=>{
const v=videoDom.current
if(play){
setPause(false)
v.play()
}else{
setPause(true)
v.pause()
}
}
// 拖動(dòng)slider時(shí)改變視頻currentTime
const onSliderChange=(e)=>{
setCurTime(e.target.value)
videoDom.current.currentTime=e.target.value
}
// 監(jiān)聽(tīng)video timeupdate
const onTimeUpdate=()=>{
const v=videoDom.current
setCurTime(v.currentTime)
if(v.ended){
handlePlay(false)
v.currentTime=0
}
}
// 卡頓時(shí),顯示加載中提示
const onWaiting=()=>{
setWaiting(true)
}
// 可以播放時(shí),隱藏加載中提示
const onCanPlay=()=>{
setWaiting(false)
}
return <div className="video-wrapper">
<video ref={videoDom} src={src} onLoadedMetadata={onLoad} onTimeUpdate={onTimeUpdate} onWaiting={onWaiting} onCanPlay={onCanPlay} ></video>
{/* 視頻加載時(shí)顯示loading */}
{waiting && <div className="waiting">loading...</div>}
<div className="video-controls">
{/* 播放按鈕 */}
{isPause? <button onClick={()=>{handlePlay(true)}}>播放</button>: <button onClick={()=>{handlePlay(false)}}>暫停</button>}
{/* 進(jìn)度條 */}
<input type="range" min="0" max={duration} value={curTime} onChange={onSliderChange}/>
{/* 時(shí)間信息和分辨率信息 */}
<span>{formatDuration(curTime)}/{formatDuration(duration)}</span>
<span>分辨率:{size.width}x{size.height}</span>
</div>
</div>
}
export default VideoPlayer
樣式寫(xiě)了一點(diǎn)點(diǎn),VideoPlayer.css
.video-wrapper{
width:800px;
}
.video-wrapper>video{
width: 100%;
}
.video-controls{
margin-top: 20px;
}
本文的重點(diǎn)不在于React,React只是一個(gè)載體,同樣的邏輯可以很容易地用Vue實(shí)現(xiàn),重點(diǎn)在于自定義一個(gè)視頻播放器的邏輯。
總結(jié)
到此這篇關(guān)于瀏覽器中視頻播放器實(shí)現(xiàn)的基本思路與代碼的文章就介紹到這了,更多相關(guān)瀏覽器中視頻播放器實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React18?中的?Suspense?API使用實(shí)例詳解
這篇文章主要為大家介紹了React18?中的?Suspense?API使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React?數(shù)據(jù)共享useContext的實(shí)現(xiàn)
本文主要介紹了React?數(shù)據(jù)共享useContext的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04
React實(shí)現(xiàn)點(diǎn)擊切換組件效果
這篇文章主要為大家詳細(xì)介紹了如何基于React實(shí)現(xiàn)點(diǎn)擊切換組件效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以學(xué)習(xí)一下2023-08-08
react axios配置代理(proxy),如何解決本地開(kāi)發(fā)時(shí)的跨域問(wèn)題
這篇文章主要介紹了react axios配置代理(proxy),如何解決本地開(kāi)發(fā)時(shí)的跨域問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
react數(shù)據(jù)管理機(jī)制React.Context源碼解析
這篇文章主要為大家介紹了react數(shù)據(jù)管理機(jī)制React.Context源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
React中使用Axios進(jìn)行HTTP請(qǐng)求
這篇文章主要為大家展示了如何在 React 中使用 Axios 進(jìn)行 HTTP 請(qǐng)求,包括 GET 和 POST 請(qǐng)求的使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
解決React報(bào)錯(cuò)`value` prop on `input` should&
這篇文章主要為大家介紹了React報(bào)錯(cuò)`value` prop on `input` should not be null解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
create-react-app項(xiàng)目配置全解析
這篇文章主要為大家介紹了create-react-app項(xiàng)目配置全解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
字節(jié)封裝React組件手機(jī)號(hào)自動(dòng)校驗(yàn)格式FormItem
這篇文章主要為大家介紹了字節(jié)封裝React組件手機(jī)號(hào)自動(dòng)校驗(yàn)格式FormItem,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

