Feat: expire and reload live
This commit is contained in:
parent
ea5ea5d4b1
commit
448bd355ef
|
@ -79,8 +79,8 @@ const newSyncControl = (art: Artplayer, publishStatus: (msg: ElementMessage) =>
|
|||
|
||||
export const newSyncPlugin = (
|
||||
publishStatus: (msg: ElementMessage) => boolean,
|
||||
dynamicStatus: MovieStatus,
|
||||
dynamicExpireId: () => number
|
||||
initStatus: MovieStatus,
|
||||
dynamicCurrentExpireId: () => number
|
||||
) => {
|
||||
return (art: Artplayer): syncPlugin => {
|
||||
const playingStatusDebounce = debounces(debounceTime);
|
||||
|
@ -134,7 +134,7 @@ export const newSyncPlugin = (
|
|||
const publishPlayDebounce = playingStatusDebounce(publishPlay);
|
||||
|
||||
const setAndNoPublishPlay = async () => {
|
||||
if (art.option.isLive || art.playing) return;
|
||||
if (art.playing) return;
|
||||
await artPlay(art);
|
||||
};
|
||||
|
||||
|
@ -156,7 +156,7 @@ export const newSyncPlugin = (
|
|||
const publishPauseDebounce = playingStatusDebounce(publishPause);
|
||||
|
||||
const setAndNoPublishPause = () => {
|
||||
if (art.option.isLive || !art.playing) return;
|
||||
if (!art.playing) return;
|
||||
art.video.pause();
|
||||
};
|
||||
|
||||
|
@ -184,26 +184,33 @@ export const newSyncPlugin = (
|
|||
art.playbackRate = rate;
|
||||
};
|
||||
|
||||
const checkSeek = () => {
|
||||
const checkStatus = () => {
|
||||
// 距离上一次seek超过10s后才会检查seek
|
||||
if (Date.now() - lastestSeek < 10000 || art.option.isLive) return;
|
||||
art.duration - art.currentTime > 5 &&
|
||||
publishStatus(
|
||||
ElementMessage.create({
|
||||
type: ElementMessageType.CHECK,
|
||||
type: ElementMessageType.CHECK_STATUS,
|
||||
time: Date.now(),
|
||||
checkReq: {
|
||||
status: {
|
||||
playing: art.playing,
|
||||
seek: art.currentTime,
|
||||
rate: art.playbackRate
|
||||
},
|
||||
expireId: dynamicExpireId()
|
||||
checkStatusReq: {
|
||||
playing: art.playing,
|
||||
seek: art.currentTime,
|
||||
rate: art.playbackRate
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const checkExpire = () => {
|
||||
publishStatus(
|
||||
ElementMessage.create({
|
||||
type: ElementMessageType.CHECK_EXPIRED,
|
||||
time: Date.now(),
|
||||
expireId: dynamicCurrentExpireId()
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const setAndNoPublishStatus = async (status: MovieStatus) => {
|
||||
if (!art.option.isLive) {
|
||||
setAndNoPublishRate(status.rate);
|
||||
|
@ -220,31 +227,28 @@ export const newSyncPlugin = (
|
|||
};
|
||||
};
|
||||
|
||||
const intervals: number[] = [];
|
||||
const watchers: WatchStopHandle[] = [];
|
||||
art.on("destroy", () => {
|
||||
intervals.forEach((interval) => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
watchers.forEach((watcher) => {
|
||||
watcher();
|
||||
});
|
||||
});
|
||||
|
||||
if (!art.option.isLive) {
|
||||
art.once("ready", async () => {
|
||||
console.log("同步进度中...");
|
||||
art.currentTime = dynamicStatus.seek;
|
||||
art.playbackRate = dynamicStatus.rate;
|
||||
if (dynamicStatus.playing) {
|
||||
art.currentTime = initStatus.seek;
|
||||
art.playbackRate = initStatus.rate;
|
||||
if (initStatus.playing) {
|
||||
await artPlay(art);
|
||||
}
|
||||
|
||||
const intervals: number[] = [];
|
||||
const watchers: WatchStopHandle[] = [];
|
||||
|
||||
intervals.push(setInterval(checkSeek, 10000));
|
||||
watchers.push(
|
||||
watch(
|
||||
dynamicStatus,
|
||||
async (newStatus) => {
|
||||
console.log("同步进度中...");
|
||||
setAndNoPublishRate(newStatus.rate);
|
||||
setAndNoPublishSeek(newStatus.seek);
|
||||
newStatus.playing ? await setAndNoPublishPlay() : setAndNoPublishPause();
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
);
|
||||
intervals.push(setInterval(checkStatus, 10000));
|
||||
intervals.push(setInterval(checkExpire, 10000));
|
||||
|
||||
newSyncControl(art, publishStatus);
|
||||
|
||||
|
@ -260,12 +264,6 @@ export const newSyncPlugin = (
|
|||
art.on("video:ratechange", publishRate);
|
||||
|
||||
art.on("destroy", () => {
|
||||
intervals.forEach((interval) => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
watchers.forEach((watcher) => {
|
||||
watcher();
|
||||
});
|
||||
art.off("play", publishPlayDebounce);
|
||||
art.off("pause", publishPauseDebounce);
|
||||
art.off("seek", publishSeekDebounce);
|
||||
|
@ -274,7 +272,8 @@ export const newSyncPlugin = (
|
|||
});
|
||||
} else {
|
||||
art.once("ready", () => {
|
||||
artPlay(art);
|
||||
setAndNoPublishPlay();
|
||||
intervals.push(setInterval(checkExpire, 10000));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ enum ElementMessageType {
|
|||
CHAT_MESSAGE = 2;
|
||||
PLAY = 3;
|
||||
PAUSE = 4;
|
||||
CHECK = 5;
|
||||
CHECK_STATUS = 5;
|
||||
TOO_FAST = 6;
|
||||
TOO_SLOW = 7;
|
||||
CHANGE_RATE = 8;
|
||||
|
@ -19,6 +19,7 @@ enum ElementMessageType {
|
|||
PEOPLE_CHANGED = 12;
|
||||
SYNC_MOVIE_STATUS = 13;
|
||||
CURRENT_EXPIRED = 14;
|
||||
CHECK_EXPIRED = 15;
|
||||
}
|
||||
|
||||
message ChatResp {
|
||||
|
@ -42,11 +43,6 @@ message MovieStatusChanged {
|
|||
MovieStatus status = 2;
|
||||
}
|
||||
|
||||
message CheckReq {
|
||||
MovieStatus status = 1;
|
||||
uint64 expireId = 2;
|
||||
}
|
||||
|
||||
message ElementMessage {
|
||||
ElementMessageType type = 1;
|
||||
int64 time = 2;
|
||||
|
@ -56,7 +52,8 @@ message ElementMessage {
|
|||
MovieStatus changeMovieStatusReq = 6;
|
||||
MovieStatusChanged movieStatusChanged = 7;
|
||||
double changeSeekReq = 8;
|
||||
CheckReq checkReq = 9;
|
||||
MovieStatus checkStatusReq = 9;
|
||||
uint64 expireId = 10;
|
||||
int64 peopleChanged = 11;
|
||||
Sender moviesChanged = 12;
|
||||
Sender currentChanged = 13;
|
||||
|
|
|
@ -10,7 +10,7 @@ export enum ElementMessageType {
|
|||
CHAT_MESSAGE = 2,
|
||||
PLAY = 3,
|
||||
PAUSE = 4,
|
||||
CHECK = 5,
|
||||
CHECK_STATUS = 5,
|
||||
TOO_FAST = 6,
|
||||
TOO_SLOW = 7,
|
||||
CHANGE_RATE = 8,
|
||||
|
@ -20,6 +20,7 @@ export enum ElementMessageType {
|
|||
PEOPLE_CHANGED = 12,
|
||||
SYNC_MOVIE_STATUS = 13,
|
||||
CURRENT_EXPIRED = 14,
|
||||
CHECK_EXPIRED = 15,
|
||||
UNRECOGNIZED = -1,
|
||||
}
|
||||
|
||||
|
@ -41,8 +42,8 @@ export function elementMessageTypeFromJSON(object: any): ElementMessageType {
|
|||
case "PAUSE":
|
||||
return ElementMessageType.PAUSE;
|
||||
case 5:
|
||||
case "CHECK":
|
||||
return ElementMessageType.CHECK;
|
||||
case "CHECK_STATUS":
|
||||
return ElementMessageType.CHECK_STATUS;
|
||||
case 6:
|
||||
case "TOO_FAST":
|
||||
return ElementMessageType.TOO_FAST;
|
||||
|
@ -70,6 +71,9 @@ export function elementMessageTypeFromJSON(object: any): ElementMessageType {
|
|||
case 14:
|
||||
case "CURRENT_EXPIRED":
|
||||
return ElementMessageType.CURRENT_EXPIRED;
|
||||
case 15:
|
||||
case "CHECK_EXPIRED":
|
||||
return ElementMessageType.CHECK_EXPIRED;
|
||||
case -1:
|
||||
case "UNRECOGNIZED":
|
||||
default:
|
||||
|
@ -89,8 +93,8 @@ export function elementMessageTypeToJSON(object: ElementMessageType): string {
|
|||
return "PLAY";
|
||||
case ElementMessageType.PAUSE:
|
||||
return "PAUSE";
|
||||
case ElementMessageType.CHECK:
|
||||
return "CHECK";
|
||||
case ElementMessageType.CHECK_STATUS:
|
||||
return "CHECK_STATUS";
|
||||
case ElementMessageType.TOO_FAST:
|
||||
return "TOO_FAST";
|
||||
case ElementMessageType.TOO_SLOW:
|
||||
|
@ -109,6 +113,8 @@ export function elementMessageTypeToJSON(object: ElementMessageType): string {
|
|||
return "SYNC_MOVIE_STATUS";
|
||||
case ElementMessageType.CURRENT_EXPIRED:
|
||||
return "CURRENT_EXPIRED";
|
||||
case ElementMessageType.CHECK_EXPIRED:
|
||||
return "CHECK_EXPIRED";
|
||||
case ElementMessageType.UNRECOGNIZED:
|
||||
default:
|
||||
return "UNRECOGNIZED";
|
||||
|
@ -136,11 +142,6 @@ export interface MovieStatusChanged {
|
|||
status: MovieStatus | undefined;
|
||||
}
|
||||
|
||||
export interface CheckReq {
|
||||
status: MovieStatus | undefined;
|
||||
expireId: number;
|
||||
}
|
||||
|
||||
export interface ElementMessage {
|
||||
type: ElementMessageType;
|
||||
time: number;
|
||||
|
@ -150,7 +151,8 @@ export interface ElementMessage {
|
|||
changeMovieStatusReq: MovieStatus | undefined;
|
||||
movieStatusChanged: MovieStatusChanged | undefined;
|
||||
changeSeekReq: number;
|
||||
checkReq: CheckReq | undefined;
|
||||
checkStatusReq: MovieStatus | undefined;
|
||||
expireId: number;
|
||||
peopleChanged: number;
|
||||
moviesChanged: Sender | undefined;
|
||||
currentChanged: Sender | undefined;
|
||||
|
@ -473,82 +475,6 @@ export const MovieStatusChanged = {
|
|||
},
|
||||
};
|
||||
|
||||
function createBaseCheckReq(): CheckReq {
|
||||
return { status: undefined, expireId: 0 };
|
||||
}
|
||||
|
||||
export const CheckReq = {
|
||||
encode(message: CheckReq, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
if (message.status !== undefined) {
|
||||
MovieStatus.encode(message.status, writer.uint32(10).fork()).ldelim();
|
||||
}
|
||||
if (message.expireId !== 0) {
|
||||
writer.uint32(16).uint64(message.expireId);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): CheckReq {
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseCheckReq();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.status = MovieStatus.decode(reader, reader.uint32());
|
||||
continue;
|
||||
case 2:
|
||||
if (tag !== 16) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.expireId = longToNumber(reader.uint64() as Long);
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): CheckReq {
|
||||
return {
|
||||
status: isSet(object.status) ? MovieStatus.fromJSON(object.status) : undefined,
|
||||
expireId: isSet(object.expireId) ? globalThis.Number(object.expireId) : 0,
|
||||
};
|
||||
},
|
||||
|
||||
toJSON(message: CheckReq): unknown {
|
||||
const obj: any = {};
|
||||
if (message.status !== undefined) {
|
||||
obj.status = MovieStatus.toJSON(message.status);
|
||||
}
|
||||
if (message.expireId !== 0) {
|
||||
obj.expireId = Math.round(message.expireId);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<CheckReq>, I>>(base?: I): CheckReq {
|
||||
return CheckReq.fromPartial(base ?? ({} as any));
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<CheckReq>, I>>(object: I): CheckReq {
|
||||
const message = createBaseCheckReq();
|
||||
message.status = (object.status !== undefined && object.status !== null)
|
||||
? MovieStatus.fromPartial(object.status)
|
||||
: undefined;
|
||||
message.expireId = object.expireId ?? 0;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseElementMessage(): ElementMessage {
|
||||
return {
|
||||
type: 0,
|
||||
|
@ -559,7 +485,8 @@ function createBaseElementMessage(): ElementMessage {
|
|||
changeMovieStatusReq: undefined,
|
||||
movieStatusChanged: undefined,
|
||||
changeSeekReq: 0,
|
||||
checkReq: undefined,
|
||||
checkStatusReq: undefined,
|
||||
expireId: 0,
|
||||
peopleChanged: 0,
|
||||
moviesChanged: undefined,
|
||||
currentChanged: undefined,
|
||||
|
@ -592,8 +519,11 @@ export const ElementMessage = {
|
|||
if (message.changeSeekReq !== 0) {
|
||||
writer.uint32(65).double(message.changeSeekReq);
|
||||
}
|
||||
if (message.checkReq !== undefined) {
|
||||
CheckReq.encode(message.checkReq, writer.uint32(74).fork()).ldelim();
|
||||
if (message.checkStatusReq !== undefined) {
|
||||
MovieStatus.encode(message.checkStatusReq, writer.uint32(74).fork()).ldelim();
|
||||
}
|
||||
if (message.expireId !== 0) {
|
||||
writer.uint32(80).uint64(message.expireId);
|
||||
}
|
||||
if (message.peopleChanged !== 0) {
|
||||
writer.uint32(88).int64(message.peopleChanged);
|
||||
|
@ -675,7 +605,14 @@ export const ElementMessage = {
|
|||
break;
|
||||
}
|
||||
|
||||
message.checkReq = CheckReq.decode(reader, reader.uint32());
|
||||
message.checkStatusReq = MovieStatus.decode(reader, reader.uint32());
|
||||
continue;
|
||||
case 10:
|
||||
if (tag !== 80) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.expireId = longToNumber(reader.uint64() as Long);
|
||||
continue;
|
||||
case 11:
|
||||
if (tag !== 88) {
|
||||
|
@ -721,7 +658,8 @@ export const ElementMessage = {
|
|||
? MovieStatusChanged.fromJSON(object.movieStatusChanged)
|
||||
: undefined,
|
||||
changeSeekReq: isSet(object.changeSeekReq) ? globalThis.Number(object.changeSeekReq) : 0,
|
||||
checkReq: isSet(object.checkReq) ? CheckReq.fromJSON(object.checkReq) : undefined,
|
||||
checkStatusReq: isSet(object.checkStatusReq) ? MovieStatus.fromJSON(object.checkStatusReq) : undefined,
|
||||
expireId: isSet(object.expireId) ? globalThis.Number(object.expireId) : 0,
|
||||
peopleChanged: isSet(object.peopleChanged) ? globalThis.Number(object.peopleChanged) : 0,
|
||||
moviesChanged: isSet(object.moviesChanged) ? Sender.fromJSON(object.moviesChanged) : undefined,
|
||||
currentChanged: isSet(object.currentChanged) ? Sender.fromJSON(object.currentChanged) : undefined,
|
||||
|
@ -754,8 +692,11 @@ export const ElementMessage = {
|
|||
if (message.changeSeekReq !== 0) {
|
||||
obj.changeSeekReq = message.changeSeekReq;
|
||||
}
|
||||
if (message.checkReq !== undefined) {
|
||||
obj.checkReq = CheckReq.toJSON(message.checkReq);
|
||||
if (message.checkStatusReq !== undefined) {
|
||||
obj.checkStatusReq = MovieStatus.toJSON(message.checkStatusReq);
|
||||
}
|
||||
if (message.expireId !== 0) {
|
||||
obj.expireId = Math.round(message.expireId);
|
||||
}
|
||||
if (message.peopleChanged !== 0) {
|
||||
obj.peopleChanged = Math.round(message.peopleChanged);
|
||||
|
@ -788,9 +729,10 @@ export const ElementMessage = {
|
|||
? MovieStatusChanged.fromPartial(object.movieStatusChanged)
|
||||
: undefined;
|
||||
message.changeSeekReq = object.changeSeekReq ?? 0;
|
||||
message.checkReq = (object.checkReq !== undefined && object.checkReq !== null)
|
||||
? CheckReq.fromPartial(object.checkReq)
|
||||
message.checkStatusReq = (object.checkStatusReq !== undefined && object.checkStatusReq !== null)
|
||||
? MovieStatus.fromPartial(object.checkStatusReq)
|
||||
: undefined;
|
||||
message.expireId = object.expireId ?? 0;
|
||||
message.peopleChanged = object.peopleChanged ?? 0;
|
||||
message.moviesChanged = (object.moviesChanged !== undefined && object.moviesChanged !== null)
|
||||
? Sender.fromPartial(object.moviesChanged)
|
||||
|
|
|
@ -19,7 +19,7 @@ import { useMovieApi } from "@/hooks/useMovie";
|
|||
import { useRoomApi, useRoomPermission } from "@/hooks/useRoom";
|
||||
import artplayerPluginDanmuku from "artplayer-plugin-danmuku";
|
||||
import { strLengthLimit, blobToUint8Array, formatTime } from "@/utils";
|
||||
import { ElementMessage, ElementMessageType } from "@/proto/message";
|
||||
import { ElementMessage, ElementMessageType, MovieStatus } from "@/proto/message";
|
||||
import type { options } from "@/components/Player.vue";
|
||||
import RoomInfo from "@/components/cinema/RoomInfo.vue";
|
||||
import MovieList from "@/components/cinema/MovieList.vue";
|
||||
|
@ -140,6 +140,7 @@ const playerOption = computed<options>(() => {
|
|||
danmuku: [],
|
||||
speed: 4
|
||||
}),
|
||||
// WARN: room.currentStatus 变了会导致重载
|
||||
newSyncPlugin(sendElement, room.currentStatus, () => room.currentExpireId)
|
||||
]
|
||||
};
|
||||
|
@ -206,6 +207,11 @@ const getPlayerInstance = (art: Artplayer) => {
|
|||
player = art;
|
||||
};
|
||||
|
||||
const setPlayerStatus = (status: MovieStatus) => {
|
||||
if (!player) return;
|
||||
player.plugins["syncPlugin"].setAndNoPublishStatus(status);
|
||||
};
|
||||
|
||||
const { state: currentMovie, execute: reqCurrentMovieApi } = currentMovieApi();
|
||||
const switchCurrentMovie = async () => {
|
||||
try {
|
||||
|
@ -226,9 +232,7 @@ const switchCurrentMovie = async () => {
|
|||
room.currentExpireId = currentExpireId;
|
||||
player.once("video:canplay", () => {
|
||||
if (room.currentExpireId != currentExpireId) return;
|
||||
room.currentStatus.playing = currentStatus.playing;
|
||||
room.currentStatus.seek = currentStatus.seek;
|
||||
room.currentStatus.rate = currentStatus.rate;
|
||||
setPlayerStatus(currentStatus);
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.log(err);
|
||||
|
@ -297,13 +301,11 @@ const handleElementMessage = (msg: ElementMessage) => {
|
|||
});
|
||||
break;
|
||||
}
|
||||
room.currentStatus.playing = msg.movieStatusChanged!.status!.playing;
|
||||
room.currentStatus.seek = msg.movieStatusChanged!.status!.seek;
|
||||
room.currentStatus.rate = msg.movieStatusChanged!.status!.rate;
|
||||
setPlayerStatus(msg.movieStatusChanged!.status!);
|
||||
break;
|
||||
}
|
||||
|
||||
case ElementMessageType.CHECK: {
|
||||
case ElementMessageType.CHECK_STATUS: {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue