TeaWeb/shared/js/ui/frames/video/Definitions.ts
2021-01-06 18:44:30 +01:00

168 lines
No EOL
4.8 KiB
TypeScript

import {ClientIcon} from "svg-sprites/client-icons";
import {VideoBroadcastType} from "tc-shared/connection/VideoConnection";
import {LogCategory, logWarn} from "tc-shared/log";
export const kLocalVideoId = "__local__video__";
export const kLocalBroadcastChannels: VideoBroadcastType[] = ["screen", "camera"];
export type ChannelVideoInfo = { clientName: string, clientUniqueId: string, clientId: number, statusIcon: ClientIcon };
export type ChannelVideoStreamState = "available" | "streaming" | "ignored" | "none";
export type VideoStatistics = {
type: "sender",
mode: "camara" | "screen",
dimensions: { width: number, height: number },
frameRate: number,
codec: { name: string, payloadType: number }
maxBandwidth: number,
bandwidth: number,
qualityLimitation: "cpu" | "bandwidth",
source: {
frameRate: number,
dimensions: { width: number, height: number },
}
} | {
type: "receiver",
mode: "camara" | "screen",
dimensions: { width: number, height: number },
frameRate: number,
codec: { name: string, payloadType: number }
};
export type VideoStreamState = {
state: "disconnected"
} | {
state: "available"
} | {
state: "connecting"
} | {
/* like join failed or whatever */
state: "failed",
reason?: string
} | {
state: "connected",
stream: MediaStream
};
export type VideoSubscribeInfo = {
totalSubscriptions: number,
subscribedStreams: {[T in VideoBroadcastType]: number},
subscribeLimits: {[T in VideoBroadcastType]?: number},
maxSubscriptions: number | undefined
};
/**
* "muted": The video has been muted locally
* "unset": The video will be normally played
* "empty": No video available
*/
export type LocalVideoState = "muted" | "unset" | "empty";
export interface ChannelVideoEvents {
action_toggle_expended: { expended: boolean },
action_video_scroll: { direction: "left" | "right" },
action_set_spotlight: { videoId: string | undefined, expend: boolean },
action_focus_spotlight: {},
action_set_fullscreen: { videoId: string | undefined },
action_set_pip: { videoId: string | undefined, broadcastType: VideoBroadcastType },
action_toggle_mute: { videoId: string, broadcastType: VideoBroadcastType | undefined, muted: boolean },
action_dismiss: { videoId: string, broadcastType: VideoBroadcastType },
query_expended: {},
query_videos: {},
query_video: { videoId: string },
query_video_info: { videoId: string },
query_video_statistics: { videoId: string, broadcastType: VideoBroadcastType },
query_spotlight: {},
query_video_stream: { videoId: string, broadcastType: VideoBroadcastType },
query_subscribe_info: {}
notify_expended: { expended: boolean },
notify_videos: {
videoIds: string[]
},
notify_video: {
videoId: string,
cameraStream: ChannelVideoStreamState,
screenStream: ChannelVideoStreamState,
},
notify_video_info: {
videoId: string,
info: ChannelVideoInfo
},
notify_video_info_status: {
videoId: string,
statusIcon: ClientIcon
},
notify_video_arrows: {
left: boolean,
right: boolean
},
notify_spotlight: {
videoId: string | undefined
},
notify_video_statistics: {
videoId: string | undefined,
broadcastType: VideoBroadcastType,
statistics: VideoStatistics
},
notify_video_stream: {
videoId: string,
broadcastType: VideoBroadcastType,
state: VideoStreamState
},
notify_subscribe_info: {
info: VideoSubscribeInfo
}
}
export function makeVideoAutoplay(video: HTMLVideoElement) : () => void {
let replayTimeout;
video.autoplay = true;
const executePlay = () => {
if(replayTimeout) {
return;
}
video.play().then(undefined).catch(() => {
logWarn(LogCategory.VIDEO, tr("Failed to start video replay. Retrying in 500ms intervals."));
replayTimeout = setInterval(() => {
video.play().then(() => {
clearInterval(replayTimeout);
replayTimeout = undefined;
}).catch(() => {});
});
});
};
const listenerPause = () => {
logWarn(LogCategory.VIDEO, tr("Video replay paused. Executing play again."));
executePlay();
};
const listenerEnded = () => {
logWarn(LogCategory.VIDEO, tr("Video replay ended. Executing play again."));
executePlay();
};
video.addEventListener("pause", listenerPause);
video.addEventListener("ended", listenerEnded);
executePlay();
return () => {
clearTimeout(replayTimeout);
video.removeEventListener("pause", listenerPause);
video.removeEventListener("ended", listenerEnded);
};
}