Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
80acc6c
feat: 整体框架
wudechang May 8, 2025
2fec647
fix: 部分代码
wudechang May 12, 2025
572c711
feat: 跑通流程
wudechang May 14, 2025
b427bca
fix: 修复media交互bug
wudechang May 15, 2025
43e4ccc
fix: umd导出mis
wudechang May 20, 2025
a0a0445
fix: url为空报错
wudechang May 20, 2025
de4a1cb
feat: 修改postMessage
xinghui-lc May 20, 2025
9eb735d
feat: 修改getFinalUrl方法
xinghui-lc May 20, 2025
7e9f82a
fix: url+protol
wudechang May 20, 2025
76fb9a4
fix: 发布版本
wudechang May 21, 2025
326ab5b
fix: 重置handleSource
wudechang May 21, 2025
a0b168f
fix: 修复retry报错
wudechang May 22, 2025
40585b1
feat: 修改提前拿到预拉流结果时,传递stream失败
xinghui-lc May 26, 2025
c2f0df4
feat: 更新低端浏览器没有globalThis
xinghui-lc Jun 16, 2025
20591b9
feat: 兼容this.flv不存在时场景
xinghui-lc Jun 16, 2025
542cbf2
feat: 升级版本
xinghui-lc Jun 16, 2025
bc203a4
feat: 更新
xinghui-lc Jun 25, 2025
72718b7
fix: core event listener
wudechang Jun 25, 2025
1e727c6
fix: 删除无法直接copy的对象
wudechang Jun 30, 2025
cccc704
feat: worker提前初始化
xinghui-lc Jul 9, 2025
844b734
fix: 更改初始化worker方式
wudechang Jul 9, 2025
ea1aada
feat: 发版
wudechang Jul 9, 2025
d5263c3
fix: umd暴露
wudechang Jul 9, 2025
1eb4613
fix: mse in worker暴露basedts
wudechang Sep 19, 2025
d2b2d33
chore: 🤖 release xgplayer-flv 3.0.23-beta.14
gemxx Sep 22, 2025
60b37eb
feat: 🎸 (xgplayer) add runHooks method to enhance hook functionality
gemxx Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 47 additions & 44 deletions fixtures/flv/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Player from '../../packages/xgplayer/src'
import FlvPlayer from '../../packages/xgplayer-flv/src'
import FlvPlayer, { MIW, preParePlayerWorker } from '../../packages/xgplayer-flv/src'

// localStorage.setItem('xgd', 1)
function defaultOpt() {
Expand All @@ -17,23 +17,24 @@ function defaultOpt() {
maxReaderInterval: 5000,
seamlesslyReload: false,
firstMaxChunkSize: 20000,
manualLoad: true
manualLoad: false
}
}
var cachedOpt = localStorage.getItem('xg:test:flv:opt')
try { cachedOpt = JSON.parse(cachedOpt) } catch (error) { cachedOpt = undefined }
cachedOpt.manualLoad = false
var opts = Object.assign({
// url: 'https://1011.hlsplay.aodianyun.com/demo/game.flv',
url: 'https://pull-flv-l1.douyincdn.com/stage/stream-399911386870710302_ld.flv?keeptime=00093a80&wsSecret=84c8c84e064fb6c6aaad6ec54c5c8247&wsTime=63315a10&abr_pts=1950715',
url: 'https://pull-demo.volcfcdnrd.com/live/st-4536524.flv',
}, defaultOpt(), cachedOpt)
var testPoint = Number(localStorage.getItem('xg:test:flv:point'))

if (isNaN(testPoint)) testPoint = 0

window.onload = function () {
fetch('https://pull-demo.volcfcdnrd.com/live/st-4536524.flv').then(res => {
window.streamRes = res
})
// fetch('https://pull-demo.volcfcdnrd.com/live/st-4536524.flv').then(res => {
// window.streamRes = res.body
// })
var dTestPoint = document.getElementById('test-point')
var dTestPointDesc = document.getElementById('test-point-desc')

Expand Down Expand Up @@ -113,14 +114,16 @@ window.onload = function () {
window.timeStart = Date.now()
window.player = player = new Player({
el: document.getElementById('player'),
plugins: [FlvPlayer],
plugins: [MIW],
// plugins:[FlvPlayer],
url: opts.url,
isLive: opts.isLive,
autoplay: opts.autoplay,
autoplayMuted: opts.autoplayMuted,
flv: {
// streamRes: window.streamRes,
...opts
...opts,
worker: preParePlayerWorker()
}
});
player.once('ready', () => {
Expand All @@ -134,9 +137,9 @@ window.onload = function () {
dlError.innerHTML = ''

function pushEvent(name, value, container) {
if (name === 'loadeddata') {
if (name === 'loadeddata') {
console.log('loadeddata', Date.now() - window.timeStart)
player.plugins.flv.flv._mediaLoader._currentTask._loader._firstMaxChunkSize = null
// player.plugins.flv.flv._mediaLoader._currentTask._loader._firstMaxChunkSize = null
}
container = container || dlEvent
if (container === dlEvent && dlLogPause.checked) return
Expand Down Expand Up @@ -271,10 +274,10 @@ window.onload = function () {
inp(doMaxLatency).onchange = function () { updateOpts('maxLatency', this.value, 'number') }
inp(doDisconnectTime).onchange = function () { updateOpts('disconnectTime', this.value, 'number') }
inp(doMaxReaderInterval).onchange = function () { updateOpts('maxReaderInterval', this.value, 'number') }

// MIW._playerWorker();//初始化worker
setTimeout(() => {
initPlayer()
}, 3000)
},200)

dbResetOpt.onclick = resetOpts
dbApplyOpt.onclick = initPlayer
Expand Down Expand Up @@ -305,40 +308,40 @@ window.onload = function () {
resetOpts()
}

setTimeout(function () {
var lastPlayback = null
var fps = 0
var prevTime = 0
setInterval(function () {
if (player && player.plugins.flv) {
var t = player.currentTime
prevTime = t
var flv = player.plugins.flv.core
var buf = flv.bufferInfo()
var pq = flv.playbackQuality()
var sp = flv.speedInfo()
if (lastPlayback) {
fps = Math.round((pq.totalVideoFrames - lastPlayback.totalVideoFrames) / (pq.creationTime - lastPlayback.creationTime) * 1000)
}
lastPlayback = pq
// setTimeout(function () {
// var lastPlayback = null
// var fps = 0
// var prevTime = 0
// setInterval(function () {
// if (player && player.plugins.flv) {
// var t = player.currentTime
// prevTime = t
// var flv = player.plugins.flv.core
// var buf = flv.bufferInfo()
// var pq = flv.playbackQuality()
// var sp = flv.speedInfo()
// if (lastPlayback) {
// fps = Math.round((pq.totalVideoFrames - lastPlayback.totalVideoFrames) / (pq.creationTime - lastPlayback.creationTime) * 1000)
// }
// lastPlayback = pq

dsBuffer.innerHTML =
'<p>当前时间:' + t + 's</p>' +
'<p>剩余缓存时长:' + buf.remaining + 's</p>' +
'<p>当前时间之前缓存时长:' + buf.behind + 's</p>' +
'<p>总缓存时长:' + buf.length + 's</p>' +
'<p>buffers:' + JSON.stringify(buf.buffers) + '</p>'
// dsBuffer.innerHTML =
// '<p>当前时间:' + t + 's</p>' +
// '<p>剩余缓存时长:' + buf.remaining + 's</p>' +
// '<p>当前时间之前缓存时长:' + buf.behind + 's</p>' +
// '<p>总缓存时长:' + buf.length + 's</p>' +
// '<p>buffers:' + JSON.stringify(buf.buffers) + '</p>'

dsFrame.innerHTML =
'<p>总渲染帧数:' + pq.totalVideoFrames + '</p>' +
'<p>掉帧数量:' + pq.droppedVideoFrames + '</p>' +
'<p>fps:' + fps + '</p>'
// dsFrame.innerHTML =
// '<p>总渲染帧数:' + pq.totalVideoFrames + '</p>' +
// '<p>掉帧数量:' + pq.droppedVideoFrames + '</p>' +
// '<p>fps:' + fps + '</p>'

dsSpeed.innerHTML =
'<p>当前速度:' + Math.round(sp.speed / (8 * 1024)) + 'KB/s</p>' +
'<p>平均速度:' + Math.round(sp.avgSpeed / (8 * 1024)) + 'KB/s</p>'
// dsSpeed.innerHTML =
// '<p>当前速度:' + Math.round(sp.speed / (8 * 1024)) + 'KB/s</p>' +
// '<p>平均速度:' + Math.round(sp.avgSpeed / (8 * 1024)) + 'KB/s</p>'

}
}, 1000)
})
// }
// }, 1000)
// })
}
2 changes: 1 addition & 1 deletion packages/xgplayer-flv/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "xgplayer-flv",
"version": "3.0.22",
"version": "3.0.23-beta.14",
"main": "dist/index.min.js",
"module": "es/index.js",
"typings": "es/index.d.ts",
Expand Down
184 changes: 184 additions & 0 deletions packages/xgplayer-flv/src/MIW.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { BasePlugin, Events, Errors } from 'xgplayer'
import { EVENT } from 'xgplayer-streaming-shared'
import Flv from './adapt/main'
import PlayerWorker from './adapt/worker?worker&inline'

export default class FlvPlugin extends BasePlugin {

static get pluginName () {
return 'flv'
}

/** @type {Flv} */
flv = null;


/** @type {Flv} */
get core () {
return this.flv
}

/** @type {string} */
get version () {
return this.flv?.version
}

get loader () {
return this.flv?.loader
}

get transferCost () {
return this.flv?.transferCost
}

beforePlayerInit () {
const config = this.player.config
const mediaElem = this.player.media || this.player.video

if (!config.url) return

if (this.flv) this.flv.destroy()

this.player.switchURL = this._onSwitchURL

const flvOpts = config.flv || {}
if (flvOpts.disconnectTime === null || flvOpts.disconnectTime === undefined) {
flvOpts.disconnectTime = 0
}
if (!flvOpts.worker) {
flvOpts.worker = preParePlayerWorker()
}
this.flv = new Flv({
isLive: config.isLive,
media: mediaElem,
preProcessUrl: (url, ext) => this.player?.preProcessUrl?.(url, ext) || {url, ext},
...flvOpts
})
if (!this.softDecode) {
BasePlugin.defineGetterOrSetter(this.player, {
url: {
get: () => {
return this.flv?.blobUrl
},
configurable: true
}
})
}

if (config.isLive) {
this.player?.useHooks('replay', () => this.flv?.replay())
}

this.on(Events.URL_CHANGE, this._onSwitchURL)
this.on(Events.DESTROY, this.destroy)

this._transError()
this._transCoreEvent(EVENT.TTFB)
this._transCoreEvent(EVENT.LOAD_START)
this._transCoreEvent(EVENT.LOAD_RESPONSE_HEADERS)
this._transCoreEvent(EVENT.LOAD_COMPLETE)
this._transCoreEvent(EVENT.LOAD_RETRY)
this._transCoreEvent(EVENT.SOURCEBUFFER_CREATED)
this._transCoreEvent(EVENT.ANALYZE_DURATION_EXCEEDED)
this._transCoreEvent(EVENT.APPEND_BUFFER)
this._transCoreEvent(EVENT.REMOVE_BUFFER)
this._transCoreEvent(EVENT.BUFFEREOS)
this._transCoreEvent(EVENT.KEYFRAME)
this._transCoreEvent(EVENT.CHASEFRAME)
this._transCoreEvent(EVENT.METADATA_PARSED)
this._transCoreEvent(EVENT.SEI)
this._transCoreEvent(EVENT.SEI_IN_TIME)
this._transCoreEvent(EVENT.FLV_SCRIPT_DATA)
this._transCoreEvent(EVENT.STREAM_EXCEPTION)
this._transCoreEvent(EVENT.SWITCH_URL_SUCCESS)
this._transCoreEvent(EVENT.SWITCH_URL_FAILED)

if (!flvOpts.manualLoad) {
this.loadSource(config.url, flvOpts.streamRes)
}
this.player.handleSource = false
}

getStats = () => {
return {}
}

loadSource = (url = this.player.config.url, stream) => {
this.flv?.load(this.player.config.url, true, stream)
}

destroy = () => {
if (this.flv) {
this.flv.destroy()
this.flv = null
}
this.player.handleSource = true
}

/**
* @param {string | boolean} [mediaType]
* @param {string} [codec]
* @returns {boolean}
* - mediaType: 默认检测 MSE 对 H264 codec是否支持,传入 true 或者配置参数的mediaType的取值检测 WebAssembly是否支持
* - codec: 暂无使用
*/
static isSupported () {
return Flv.isSupported()
}

/**
*
* @param {string} url
* @param {boolean | {seamless: boolean}} seamless
*/
_onSwitchURL = (url, seamless) => {
if (this.flv) {
this.player.config.url = url

if (typeof seamless === 'object') {
seamless = seamless.seamless
}

this.flv.switchURL(url, seamless)

if (!seamless && this.player.config?.flv?.keepStatusAfterSwitch) {
this._keepPauseStatus()
}
}
}

_keepPauseStatus = () => {
const paused = this.player.paused
if (!paused) return
this.player.once('canplay', () => {
this.player.pause()
})
}

_onDefinitionChange = ({ to }) => {
if (this.flv) this.flv.switchURL(to)
}

_transError () {
this.flv.on(EVENT.ERROR, (err) => {
if (this.player) {
this.player.emit(Events.ERROR, new Errors(this.player, err))
}
})
}

_transCoreEvent (eventName) {
this.flv.on(eventName, (e) => {
if (this.player) {
this.player.emit('core_event', {
...e,
eventName
})
}
})
}
}

export function preParePlayerWorker () {
return new PlayerWorker()
}
Loading