Here, we will learn how to start the livestream and watch started livestream in Twilio using vue.js. Last article we will show how to create the live streaming with Twilio and Node.js. Here we will call the node.js apis.
Step 1: Install the following packages:
npm install twilio-video bootstrap-vue @twilio/live-player-sdk
Step 2: Create config.js file and add the following in it:
export default { apiURL: "http://localhost:5000", };
Step 3: Open LiveStreamNode.vue file and add the following in it:
<template> <div id="container" class="container"> <div id="stream" class="flex items-center justify-center w-full"> <!-- video will be added here --> </div> <div class="buttons"> <b-button variant="success" size="md" class="mr-5 me-5" @click="startStream" v-if="!streaming" >Start Stream</b-button > <b-button variant="danger" size="md" class="mr-5 me-5" @click="endStream" v-else >Leave Stream</b-button > <b-button variant="success" @click="watchStream">Watch Stream</b-button> </div> </div> </template> <script> import { createLocalVideoTrack, connect } from "twilio-video"; import { BButton } from "bootstrap-vue"; import config from "../config"; import axios from "axios"; let liveNotification = document.createElement("div"); liveNotification.innerHTML = "LIVE"; liveNotification.id = "liveNotification"; liveNotification.classList.add( "absolute", "top-10", "left-48", "p-2", "bg-red-500", "text-white" ); export default { name: "LiveStreamNode", components: { BButton, }, data() { return { streaming: false, room: null, streamName: localStorage.getItem("roomName") || "Test Name" + Math.random() * 1000000, identity: localStorage.getItem("userName") || "Shaikh" + Math.random() * 1000000, streamDetails: null, }; }, mounted() { this.addLocalVideo(); }, methods: { watchStream() { window.open( `/watchstream?playback=${this.streamDetails.player_streamer_sid}` ); }, async joinLive() { const tokenResponse = await fetch(`${config.apiURL}/streamerToken`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ identity: this.identity, room: this.streamDetails.room_sid, }), }); const tokenData = await tokenResponse.json(); this.room = await connect(tokenData.token); }, async startStream() { // Create the livestream await axios .post(`${config.apiURL}/start`, { streamName: this.streamName }) .then(({ data }) => { if (data.status) { this.streamDetails = data.data; this.joinLive(); this.streaming = true; const stream = window.$("div#stream")[0]; const video = document.getElementsByTagName("video")[0]; stream.insertBefore(liveNotification, video); } }) .catch((error) => { console.log(error); }); }, async addLocalVideo() { const videoTrack = await createLocalVideoTrack(); const stream = window.$("div#stream")[0]; const trackElement = videoTrack.attach(); stream.appendChild(trackElement); }, async endStream() { if (this.streaming) { const data = { media_processor_sid: this.streamDetails.media_processor_sid, player_streamer_sid: this.streamDetails.player_streamer_sid, room_sid: this.streamDetails.room_sid, }; const formData = new FormData(); Object.keys(data).forEach((key) => { formData.append(key, data[key]); }); await axios .post(`${config.apiURL}/end`, formData) .then((res) => { if (res.data.status === "success") { if (this.room) { this.room.disconnect(); } this.streaming = false; liveNotification.remove(); createLocalVideoTrack().isStopped; this.$toastr.success(res.data.content); } }) .catch((error) => { console.log(error); }); } }, }, }; </script> <style> .bg-red-500 { background-color: red; } .absolute { position: absolute; } </style>
Step 4: Create a new folder public/livePlayer and add the following files in it:
- twilio-live-player-wasmworker-1-5-0.min.js - twilio-live-player-wasmworker-1-5-0.min.wasm - twilio-live-player.js - twilio-live-player.min.js
Step 5: Open WatchStreamNode.vue file and add the following in it:
<template> <div class="container mx-auto mt-10 justify-center items-center text-center"> <h1 class="text-primary">WatchStream</h1> <div id="player" class="mx-auto bg-gray-200 h-96 max-w-2xl"></div> <b-button variant="success" size="md" class="mr-5 me-5" @click="watchStream" v-if="!watchingStream" >Watch Stream</b-button > <b-button variant="danger" class="mr-5 me-5" size="md" @click="leaveStream" v-else >Leave Stream</b-button > </div> </template> <script> import { Player } from "@twilio/live-player-sdk"; import { BButton } from "bootstrap-vue"; import config from "../config"; import axios from "axios"; export default { name: "WatchStreamNode", components: { BButton, }, data() { return { token: "", watchingStream: false, player: null, }; }, mounted() { window.WatchStream = this; }, methods: { async watchStream() { try { await axios .post(`${config.apiURL}/audienceToken`, {}) .then(async (res) => { if (res.data.success) { this.token = res.data.token; const { host, protocol } = window.location; const player = await Player.connect(this.token, { playerWasmAssetsPath: `${protocol}//${host}/livePlayer`, }); this.player = player; this.watchingStream = true; setTimeout(() => { const videoElement = document.getElementById("player"); videoElement.appendChild(this.player.videoElement); this.player.play(); }, 100); } else { this.$toastr.error(res.data.data.msg); } }) .catch((error) => { this.$toastr.error(error); }); } catch (error) { console.log(error); } }, leaveStream() { if (this.player) { this.player.disconnect(); } const streamPlayer = window.$("div#player>video")[0]; if (streamPlayer) { streamPlayer.remove(); } this.watchingStream = false; }, }, }; </script>
Code in action: