How do I reference a HTML video element from the typescript class, as shown below:
File src/main/frontend/src/eyevinn-webrtc-player.ts is:
import { html, LitElement } from 'lit';
import { WebRTCPlayer } from '@eyevinn/webrtc-player';
class EyevinnWebRTCPlayer extends LitElement {
render() {
return html`
<video id="webrtc-player" controls=true autoplay=false></video>
`;
}
play(channelUrl: string) {
const video = document.getElementById('webrtc-player') as HTMLVideoElement;
const player = new WebRTCPlayer({
video: video,
type: 'whep',
statsTypeFilter: '^candidate-*|^inbound-rtp'
});
player.load(new URL(channelUrl));
player.unmute();
}
}
customElements.define('eyevinn-webrtc-player', EyevinnWebRTCPlayer);
The issue is in the following line:
const video = document.getElementById('webrtc-player') as HTMLVideoElement;
which results in null value assigned to video variable.
The corresponding Java class is:
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasSize;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.littemplate.LitTemplate;
@Tag("eyevinn-webrtc-player")
@NpmPackage(value = "@eyevinn/webrtc-player", version = "^0.13.0")
@JsModule("./src/eyevinn-webrtc-player.ts")
public class EyevinnWebrtcPlayer extends LitTemplate {
private final String whepUrl;
/**
* Construct new Eyevinn WebRTC player component.
*
* @param whepUrl the full URL to the video source, e.g. http://localhost:8889/cam1/whep
*/
public EyevinnWebrtcPlayer(final String whepUrl) {
super();
this.whepUrl = whepUrl;
}
/**
* Display the WebRTC Video player element on the web page.
*/
public void play() {
getElement ().executeJs (
String.format("return this.play('%s');", this.whepUrl));
}
}
Any idea how to invoke the play() properly and start the WebRTC stream ?
import { LitElement, html} from 'lit';
import { WebRTCPlayer } from '@eyevinn/webrtc-player';
class EyevinnWebRTCPlayer extends LitElement {
private player: WebRTCPlayer | null = null;
constructor() {
super();
console.log('EyevinnWebRTCPlayer instance created.');
}
render() {
console.log('EyevinnWebRTCPlayer rendering HTML Video element with id=webrtc-player.');
return html`
<video id="webrtc-player" controls=true autoplay=false></video>
`;
}
firstUpdated() {
console.log('EyevinnWebRTCPlayer, firstUpdated() invoked.');
const video = this._webrtcPlayer as HTMLVideoElement;
this.player = new WebRTCPlayer({
video: video,
type: 'whep',
statsTypeFilter: '^candidate-*|^inbound-rtp'
});
}
get _webrtcPlayer(): HTMLVideoElement | null {
console.log('EyevinnWebRTCPlayer, getting webrtc-player element.');
return this.renderRoot?.querySelector('#webrtc-player') ?? null;
}
play(channelUrl: string) {
console.log('EyevinnWebRTCPlayer, play() invoked.');
if (!this.player) {
console.log('EyevinnWebRTCPlayer, play() method, this.player is null !');
return;
}
this.player.load(new URL(channelUrl));
this.player.unmute();
}
stop() {
console.log('EyevinnWebRTCPlayer, stop() invoked.');
if (!this.player) {
console.log('EyevinnWebRTCPlayer, stop() method, this.player is null !');
return;
}
this.player.unload();
}
}
customElements.define('eyevinn-webrtc-player', EyevinnWebRTCPlayer);
And the Java code, EyevinnWebrtcPlayer.java is:
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.littemplate.LitTemplate;
@Tag("eyevinn-webrtc-player")
@NpmPackage(value = "@eyevinn/webrtc-player", version = "^0.13.0")
@JsModule("./src/eyevinn-webrtc-player.ts")
public class EyevinnWebrtcPlayer extends LitTemplate {
private final String whepUrl;
/**
* Construct new Eyevinn WebRTC player component.
*
* @param whepUrl the full URL to the video source, e.g. http://localhost:8889/cam1/whep
*/
public EyevinnWebrtcPlayer(final String whepUrl) {
super();
this.whepUrl = whepUrl;
}
/**
* Display the WebRTC Video player element on the web page.
*
* @param opened if true, the WebRTC session will open,
* if false it will close the WebRTC session
*/
public void play(boolean opened) {
if (opened == true) {
getElement ().executeJs (
String.format("return this.play('%s');", this.whepUrl));
}
else {
stop ();
}
}
/**
* Close the WebRTC session.
* You might invoke the {@link #play(boolean)} method with argument <i>opened</i> set to <i>false</i>.
*/
public void stop() {
getElement ().executeJs ("return this.stop();");
}
}
**NOTE: ** In this example, WebRTC player will use WHEP protocol to initiate webrtc connection towards media server or a proxy. I’ve tested with MediaMTX, and the WHEP protocol works (e.g. H.264 stream).
// java
public void play() {
getElement().callJsFunction("play", this.whepUrl));
}
Also using no shadow dom did sometimes did the trick for me when working with thrid party components. You can do this by using the element itself for rendering instead of the Lit implementation that uses the shadow root. Then document.getElementById should work again.