Skip to content

Commit

Permalink
refactor: 💡 (xgplayer-mp4-loader) 重构音频分组策略
Browse files Browse the repository at this point in the history
  • Loading branch information
gemxx committed Apr 9, 2024
1 parent d060a12 commit 6f9b066
Showing 1 changed file with 22 additions and 57 deletions.
79 changes: 22 additions & 57 deletions packages/xgplayer-mp4-loader/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ function getSegments (
range: [segFrames[0].offset, lastFrame.offset + lastFrame.size - 1],
frames: segFrames
})
time = 0

if (audioGroupingStrategy !== 1) {
time = 0
}

segFrames = []
}

Expand All @@ -259,70 +263,31 @@ function getSegments (
gopMinPtsArr = []
gopMaxPtsFrameIdxArr = []
let duration = segmentDurations[0] || segDuration
let useGroupStartStrategy = audioGroupingStrategy === 1
const vSegments = videoSegments.map((v, i, arr) => {
if (
(i === 0 && arr[i].startTime > segDuration) /* 第一帧开始时间太晚 */ ||
(i > 0 && arr[i].startTime !== arr[i - 1].endTime) /* 中间有GAP不连贯 */
) {
useGroupStartStrategy = false
}
return {
startTime: v.startTime,
endTime: v.endTime,
duration: v.duration
}
})

if (useGroupStartStrategy) {
if (frames.length > 0) {
const lastVFrame = videoSegments[videoSegments.length - 1]
const lastAFrame = frames[frames.length - 1]
const audioEndTime = (lastAFrame.pts + lastAFrame.duration) / timescale

if (!lastVFrame || lastVFrame.endTime < audioEndTime) {
let lastVSeg = vSegments.length ? vSegments[vSegments.length - 1] : null
// 补齐音视频对应的分组
do {
const startTime = lastVSeg?.endTime || 0
const endTime = startTime + segDuration
vSegments.push({
startTime,
endTime,
duration: segDuration
})
lastVSeg = vSegments[vSegments.length - 1]
} while (lastVSeg.endTime < audioEndTime)
}
}
for (let i = 0; i < l; i++) {
if (audioGroupingStrategy === 1) {
for (let i = 0, nextEndTime; i < l; i++) {
const curFrame = frames[i]
const nextFrame = frames[i + 1]
const isFinalFrame = i === l - 1
const curOrder = segments.length
segFrames.push(curFrame)
time += curFrame.duration
const curEndTime = nextEndTime || time / timescale
// 这里使用下一帧的目的是将每个分组的起始音频帧应该覆盖或包含GOP的开始时间,
// MSE在remove buffer时会将gop结束时间点的那个音频帧删掉,这个策略就是为了
// 防止之后再添加新的Coded Frame Group时由于缺少了一帧音频容易产生Buffer gap
nextEndTime = (nextFrame ? time + nextFrame.duration : 0) / timescale
if (
isFinalFrame ||
// 这里使用下一帧的目的是将每个分组的起始音频帧应该覆盖或包含GOP的开始时间,
// MSE在remove buffer时会将gop开始时间点的所在的音频帧删掉,这个策略就是为了
// 防止之后再添加新的Coded Frame Group时由于缺少了一帧音频容易产生Buffer gap
vSegments[curOrder].endTime < (nextFrame.pts + nextFrame.duration) / timescale
) {
const groupFirst = segFrames[0]
const groupLast = segFrames[segFrames.length - 1]
const groupDuration =
(groupLast.pts + groupLast.duration - groupFirst.pts) / timescale
gopMinPtsArr.push(groupFirst.pts)
gopMaxPtsFrameIdxArr.push(groupLast.index)
pushSegment(groupDuration, curOrder, curOrder)

console.log(
segments.length,
curOrder,
groupLast.duration / timescale,
vSegments[curOrder].startTime,
segments[curOrder].startTime
(
videoSegments[segments.length]
? nextEndTime > videoSegments[segments.length].endTime /* 有视频帧,使用GOP时间戳进行分割 */
: nextEndTime - segFrames[0].pts / timescale >= duration /* 无视频帧(包含音频帧大于视频时长的剩余音频帧分组的场景),使用配置的切片时间或最后一个GOP时长进行分割 */
)
) {
gopMinPtsArr.push(segFrames[0].pts)
gopMaxPtsFrameIdxArr.push(segFrames[segFrames.length - 1].index)
pushSegment(curEndTime, segments.length, segments.length)
duration = segmentDurations[segments.length] || segDuration
}
}
} else {
Expand Down

0 comments on commit 6f9b066

Please sign in to comment.