Die Video Display Calculator API ist Teil der Javascript APIs. Front-End-Javascript-Entwickler können die standardmässige Videopositionierung ausser Kraft setzen, indem sie ihr eigenes Layout implementieren und die Teilnehmervideos frei im Videocontainer positionieren.
Die Videos werden abhängig von der Containergrösse des Bereichs angezeigt, in dem der Besprechungsraum die Videos platziert. Die Position jedes Teilnehmervideos wird in absoluten Werten (x, y, Breite und Höhe) relativ zum Hauptcontainer definiert.
Auf den Dokumentationsseiten Javascript APIs und iFrame einbetten finden Sie weitere Informationen zu diesen Themen.
Begriff | Definition |
---|---|
Video, Participant Video | Der Videostream eines Teilnehmers. |
Container, Video Container | Der Bereich des Sitzungsraumes, in dem alle Videos angezeigt werden |
Das Präsentationsraum-Layout hat zwei unterschiedliche Bereiche innerhalb des Videocontainers: den primären und den sekundären Bereich.
Hinweis: Im klassischen Besprechungsraum-Layout gibt es keinen sekundären Bereich, der primäre Bereich umfasst immer den gesamten Container.
Standardmässig werden alle Videos im primären Bereich angezeigt. In diesem Fall deckt der primäre Bereich 100% des Videocontainers ab. Der Moderator kann Videos zwischen dem primären und dem sekundären Bereich verschieben. Sobald mindestens ein Video im Sekundärbereich angezeigt wird, wird der Container in zwei Teile geteilt: den Primärbereich, der 85% des Containers ausmacht, und den Sekundärbereich, der die restlichen 15% des Containers nutzt.
Der sekundäre Bereich kann um alle Ecken (oben, rechts, unten, links) verschoben werden.
Der Video Display Calculator wird immer dann ausgelöst, wenn die Videopositionen aktualisiert werden sollen. Sie müssen die absolute Position und Grösse jedes Videos innerhalb des Containers berechnen und ein Array von Video-Positions-Objekten zurückgeben.
Das System kann bis zu 12 Videocontainer anzeigen. Basierend auf Ihren eigenen Regeln und der Anzahl der Teilnehmer, können Sie entscheiden, ob Sie diese ein- oder ausblenden möchten.
Der Video Display Calculator empfängt die folgenden Parameter:
Parametername | Datentyp | Erläuterung |
---|---|---|
containerWidth | Zahl | Die Breite des Video-Containers, in Pixel |
containerHeight | Zahl | Die Höhe des Videocontainers, in Pixel |
hasSecondaryArea | boolean | true, wenn die sekundäre Anzeige sichtbar ist, sonst false. |
secondaryPosition | SecondaryVideoPosition | Der Bereich, in dem der sekundäre Videoanzeigebereich positioniert ist |
secondarySize | SecondaryVideoSize | Die Grösse des Videocontainers, in Prozent der Breite oder Höhe des gesamten Containers |
primaryParticipants | string[] | Die Liste der Teilnehmer-IDs, die dem primären Bereich zugeordnet sind |
secondaryParticipants | string[] | Die Liste der Teilnehmer-IDs, die dem sekundären Bereich zugeordnet sind |
participantsOrder | string[] | Die sortierte Liste der Teilnehmer-IDs |
particpantsMediaInformation | IParticipantsMediaInformation | Ein Objekt, das IMediaInformation für jeden der Teilnehmer in participantsOrder enthält. IMediaInformation enthält Informationen über die Grösse und den Zustand des Videos der Teilnehmer. |
hasSelfView | boolean | true, wenn es eine Selbstansicht gibt, sonst falsch |
isSelfviewInSecondary | boolean | true, wenn die Selbstansicht im sekundären Container angezeigt wird, andernfalls false |
isTVMode | boolean | true, wenn der Besprechungsraum im TV-Modus angezeigt wird, false andernfalls |
Wichtiger Hinweis: Die Teilnehmer-ID der eigenen Ansicht ist NICHT Teil des Teilnehmer-ID-Arrays (participantsOrder). Wenn es eine Selbstansicht gibt (hasSelfView === true
), können Sie sich entscheiden, die Selbstansicht hinzuzufügen. Verwenden Sie die Teilnehmer-ID myself
, um die Selbstansicht zur Ausgabedatenstruktur hinzuzufügen.
Die Ausgabestruktur enthält ein Array von Videopositionen, wobei die Positionselemente in dieser Reihenfolge auf die verfügbaren Videocontainer angewendet werden. Die Ausgabestruktur besteht auch aus einem Array von Booleschen Werten, die angeben, ob ein Element ausgeblendet werden soll oder nicht.
Parametername | Datentyp | Erläuterung |
---|---|---|
videoPositions | IVideoPosition[] | Ein Array von IVideoPosition-Objekten für alle sichtbaren Videocontainer |
hiddenContainers | boolean[] | Ein Array der Grösse 12 mit false , wenn das Video angezeigt werden soll und true , wenn das Video nicht angezeigt werden soll |
Die Schnittstelle für die Videoposition ist wie folgt definiert:
Parametername | Datentyp | Erläuterung |
---|---|---|
participantId | string | Die Teilnehmer-ID des Videos, welches in diesem Container angezeigt werden soll |
width | number | Die Breite des Videocontainers in Pixeln |
height | number | Die Höhe des Video-Containers in Pixeln |
top | number | Die Anzahl der Pixel vom oberen Rand des Containers |
left | number | Die Anzahl der Pixel vom linken Rand des Containers |
zIndex | Zahl | Der z-Index des Elements, wenn Sie die Videoanzeigen übereinander positionieren möchten |
cssClasses | string[] | CSS-Klassen, die auf den Videocontainer angewendet werden sollen. Wichtig: Die CSS-Klassen MÜSSEN mit dem Präfix 'video-container-' versehen werden |
Wenn der Video Display Calculator einen Fehler auslöst oder ein leeres Objekt zurückgibt, greift das System stattdessen auf den internen Positionsrechner zurück.
Der folgende Beispielcode platziert den ersten Teilnehmer in der Mitte des Bildschirms, alle anderen Teilnehmer in einer Reihe über dem ersten Teilnehmer und die Selbstansicht unter dem Teilnehmer:
In diesem Beispiel wird der sekundäre Bereich nicht verwendet, alle Videos werden im primären Bereich angezeigt.
const videoDisplayCalculator = {
calculatePositions: (containerWidth,
containerHeight,
hasSecondaryArea,
secondaryPosition,
secondarySize,
primaryParticipants,
secondaryParticipants,
participantsOrder,
particpantsMediaInformation,
hasSelfView,
isSelfviewInSecondary,
isTVMode) => {
const result = {
videoPositions: [],
hiddenContainers: Array(12).fill(true)
}
// Wir möchten die Videos in eine 4:3 Format anzeigen
const threeToFour = 3 / 4;
// Das Hauptvideo wird im Zentrum positioniert, 65% der gesamten Containergrösse
const mainContainerSizePercentage = 0.65
let mainContainerWidth = 0;
let mainContainerHeight = 0;
let mainContainerTop = 0;
let mainContainerLeft = 0;
if (Array.isArray(participantsOrder) && participantsOrder.length > 0) {
mainContainerWidth = containerWidth * mainContainerSizePercentage;
mainContainerHeight = mainContainerWidth * threeToFour;
if (mainContainerHeight > containerHeight * mainContainerSizePercentage) {
mainContainerHeight = containerHeight * mainContainerSizePercentage;
mainContainerWidth = mainContainerHeight / threeToFour;
}
mainContainerTop = (containerHeight - mainContainerHeight) / 2;
mainContainerLeft = (containerWidth - mainContainerWidth) / 2;
// Das Hauptvideo hinzufügen
result.videoPositions.push({
participantId: participantsOrder[0],
width: mainContainerWidth,
height: mainContainerHeight,
top: mainContainerTop,
left: mainContainerLeft,
zIndex: 1
});
result.hiddenContainers[0] = false;
const numberOfOtherVideos = participantsOrder.length - 1;
if (numberOfOtherVideos > 0) {
// Wir haben andere Videos
// Wir fügen alle anderen Videos in die obere Zeile
let otherContainersWidth = containerWidth / numberOfOtherVideos;
let otherContainersHeight = otherContainersWidth * threeToFour;
if (otherContainersHeight > mainContainerTop) {
otherContainersHeight = mainContainerTop;
otherContainersWidth = otherContainersHeight / threeToFour;
}
const otherContainersTop = (mainContainerTop - otherContainersHeight) / 2;
let otherContainersLeft = (containerWidth / 2) - ((otherContainersWidth * numberOfOtherVideos) / 2);
for (let i = 1; i < participantsOrder.length; i++) {
result.videoPositions.push({
participantId: participantsOrder[i],
width: otherContainersWidth,
height: otherContainersHeight,
top: otherContainersTop,
left: otherContainersLeft,
zIndex: 1
});
result.hiddenContainers[i] = false;
otherContainersLeft += otherContainersWidth;
}
}
}
if (hasSecondaryArea) {
// Zu implementieren
}
if (hasSelfView) {
// Wir haben eine Selbstansicht, wir fügen diese unter dem Hauptvideo hinzu
const selfViewHeight = containerHeight - mainContainerTop - mainContainerHeight;
const selfViewWidth = selfViewHeight / threeToFour;
result.videoPositions.push({
// Nota bene: Die Sebstansicht hat immer die participantId 'myself'
participantId: "myself",
width: selfViewWidth,
height: selfViewHeight,
top: containerHeight - selfViewHeight,
left: (containerWidth / 2) - (selfViewWidth / 2),
zIndex: 1
});
}
return result;
}
}
window["wlvmrApiReady"] = (handler) => {
if (!window[handler]) {
console.error(`Handler window.${handler} not found!`);
return;
}
window[handler].setVideoDisplayCalculator(videoDisplayCalculator);
}
Die folgenden Ein- und Ausgabetypen werden benutzt, um mit diesem Javascript API zu interagieren.
interface IVideoPosition {
participantId: string;
width: number;
height: number;
top: number;
left: number;
zIndex: number;
/// Wichtig: CSS Klasse MÜSSEN mit dem Prefix 'video-container-' versehen sein
cssClasses?: string[]
}
interface IVideoDisplayConfig {
videoPositions: IVideoPosition[],
hiddenContainers: boolean[]
}
export interface IMediaInformation {
audioMuted?: boolean;
videoMuted?: boolean;
hasAudio?: boolean;
hadAudio?: boolean;
offersVideo?: boolean;
hasVideo?: boolean;
hadVideo?: boolean;
videoWidth?: number;
videoHeight?: number;
}
export interface IParticipantsMediaInformation {
[participantId: string]: IMediaInformation
}
interface IVideoDisplayCalculator {
calculatePositions(
containerWidth: number,
containerHeight: number,
hasSecondaryArea: boolean,
secondaryPosition: SecondaryVideoPosition,
secondarySize: SecondaryVideoSize,
primaryParticipants: string[],
secondaryParticipants: string[],
participantsOrder: string[],
particpantsMediaInformation: IParticipantsMediaInformation,
hasSelfView: boolean,
isSelfviewInSecondary: boolean,
isTVMode: boolean
): IVideoDisplayConfig;
}
enum SecondaryVideoSize {
small = 0.15,
large = 0.5
}
type SecondaryVideoPosition = "none" | "left" | "top" | "right" | "bottom";
Sprechen Sie mit unserem Team über Ihre Pläne.