DEV Community

Cover image for Vue Streaming Tutorial: Build a Live Video Streaming App With WebRTC (WHEP)
Maria Artamonova
Maria Artamonova

Posted on Originally published at red5.net

Vue Streaming Tutorial: Build a Live Video Streaming App With WebRTC (WHEP)

Vue streaming can be added to a Vue 3 application without building a video player from scratch. In this tutorial, you will create a reusable WHEP player that accepts a Red5 Cloud host, stream name, and node group; subscribes to a live stream; and retries the connection if playback ends unexpectedly. The implementation is based on Red5’s Vue 3 + TypeScript + Vite example repository.

This specific example uses Red5 Cloud. The Red5 HTML SDK can work with Red5 Pro or Red5 Cloud, but this repository’s default red5.net host, node-group parameter, and proxy WHEP endpoint are configured for Red5 Cloud. You still need a streaming deployment because the SDK supplies the browser client, not the media server.

What You Will Build

By the end, your Vue streaming page will let a user enter connection details, start and stop playback, view connection status, and recover from a closed connection after a short delay. The player uses WHEP, a WebRTC-HTTP egress protocol designed for receiving a live WebRTC stream in a compatible client.

  • A Vue 3 component that owns the WHEP subscriber lifecycle.
  • A native video element for browser playback.
  • Configurable host, stream name, and node group fields.
  • Status and error events that the parent component can display.
  • Optional retry behavior when a live stream is interrupted.

Why Use WHEP for Vue Streaming?

Vue is responsible for the application interface and component lifecycle. WHEP is responsible for how the browser receives the WebRTC stream. Combining them keeps the player logic inside a Vue component while the Red5 HTML SDK handles session setup, events, and media playback.

For protocol background, see Red5’s guide to WHIP and WHEP and its educational overview of WebRTC. The IETF’s WHEP specification draft describes the HTTP-based session model behind the protocol.

Vue Streaming Prerequisites

  • Node.js and a Vue 3 project created with Vite. Vue’s Quick Start guide explains the current project setup.
  • A Red5 Cloud deployment with a live stream to play.
  • The Red5 Cloud host name, stream name, and node group for that deployment.
  • A browser that can play WebRTC media and permission to access the relevant deployment.

Log in to your Red5 account to create or access a Red5 Cloud deployment. If you do not have an account, sign up for a free Red5 Cloud account – no credit card required.

Install the Red5 HTML SDK

Start with a Vue 3 + TypeScript + Vite project, then install the SDK package used by the repository. The Vite alias resolves the package to its ESM build, so the Vue component can import the WHEP client directly.

npm install red5pro-webrtc-sdk

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'red5pro-webrtc-sdk': 'red5pro-webrtc-sdk/red5pro-sdk.esm.min.js',
},
},
})

Keep the alias in vite.config.ts. It matches the repository and ensures the imported client is available to the browser build.

Create a Reusable Vue Video Player

Create src/components/VideoPlayer.vue. The component receives connection properties from its parent, builds the WHEP endpoint, initializes WHEPClient, and attaches playback to a native video element. Its watcher starts or stops the subscriber when the parent changes subscribed.

import { ref, watch, onUnmounted } from 'vue' import { WHEPClient, setLogLevel } from 'red5pro-webrtc-sdk' import type { RTCWhepSubscriberConfigType } from 'red5pro-webrtc-sdk' setLogLevel('warn') const props = defineProps<{ host: string streamName: string nodeGroup: string subscribed: boolean retryEnabled?: boolean retryDelay?: number }>() const emit = defineEmits<{ (e: 'error', message: string): void (e: 'status', payload: { msg: string; retry: boolean }): void }>() const VIDEO_ELEMENT_ID = 'red5pro-subscriber' const RETRY_DELAY_MS = 2000 const client = ref<WHEPClient | null>(null) const retryTimer = ref<ReturnType<typeof setTimeout> | null>(null) const isStarting = ref(false) async function clearClient() { if (client.value) { await client.value.unsubscribe() client.value = null } } async function startSubscription() { if (isStarting.value) return isStarting.value = true try { emit('status', { msg: 'Connecting...', retry: true }) const endpoint = `https://${props.host}/as/v1/proxy/whep/live/${props.streamName}` const config: RTCWhepSubscriberConfigType = { host: props.host, streamName: props.streamName, endpoint, mediaElementId: VIDEO_ELEMENT_ID, connectionParams: { nodeGroup: props.nodeGroup }, } const subscriber = new WHEPClient() subscriber.on('*', ({ type }: { type: string }) => { if (type === 'Subscribe.Start') { emit('status', { msg: 'Live', retry: true }) emit('error', '') } }) await subscriber.init(config) await subscriber.subscribe() client.value = subscriber } catch (err) { emit('error', err instanceof Error ? err.message : String(err)) } finally { isStarting.value = false } } watch(() => props.subscribed, active => { if (active) startSubscription() else clearClient() }) onUnmounted(() => clearClient())




The repository also handles closed connections and publish-end events by clearing the client and retrying after two seconds when retry is enabled. Add that event logic when your Vue streaming experience should recover automatically from temporary interruptions.

Add Stream Configuration and Controls

The parent component keeps the editable fields and UI state separate from the player. This makes it possible to disable configuration while the application is subscribed, show a useful status label, and pass the same values into the child component as typed props.

import { ref, computed } from 'vue'
import VideoPlayer from './components/VideoPlayer.vue'

const params = new URLSearchParams(window.location.search)
const host = ref(params.get('host') ?? 'your-deployment.red5.net')
const streamName = ref(params.get('streamName') ?? 'stream1')
const nodeGroup = ref(params.get('nodeGroup') ?? 'your-node-group')
const subscribed = ref(false)
const statusMessage = ref('Idle')
const errorMessage = ref('')

const canSubscribe = computed(() =>
host.value.trim() !== '' &&
streamName.value.trim() !== '' &&
nodeGroup.value.trim() !== '',
)

function toggleSubscription() {
errorMessage.value = ''
subscribed.value = !subscribed.value
if (subscribed.value) statusMessage.value = 'Connecting...'
}

function handleStatus({ msg, retry }: { msg: string; retry: boolean }) {
statusMessage.value = msg
if (!retry) subscribed.value = false
}



{{ subscribed ? 'Unsubscribe' : 'Subscribe' }}

:host="host"
:stream-name="streamName"
:node-group="nodeGroup"
:subscribed="subscribed"
:retry-enabled="true"
@status="handleStatus"
@error="message => (errorMessage = message)"
/>

For a production app, do not expose credentials in the Vue bundle. The values in this example identify a playback destination, but authentication, authorization, and token handling should follow your deployment’s security design.

Test the Vue Streaming App

  1. Start a live stream on your Red5 Cloud deployment.
  2. Run the Vue project with npm run dev.
  3. Enter the host, stream name, and node group from the deployment, or pass them as URL query parameters.
  4. Select Subscribe and confirm that the status changes from Connecting… to Live.
  5. Stop the source stream and confirm that the player reports the expected state. If retry is enabled, restart the source and verify that the player reconnects.

If playback does not start, first verify that the stream is active and that the host, stream name, and node group match the deployment. Then inspect the browser console for the SDK error emitted by the component. The repository’s full source code includes the complete status and retry handling.

Vue Streaming Next Steps

  • Add a publisher view when the same Vue application needs to send camera or screen-share media.
  • Move host and stream configuration into a secure server-side flow rather than displaying raw connection values in the UI.
  • Add application-specific states such as a stream schedule, loading skeleton, no-live-stream message, and analytics events.
  • Use Red5 Cloud when you need a managed deployment, or review Red5 Pro when you need control over infrastructure, security, scaling, or deployment architecture.

For more browser implementation options, see Red5’s live streaming SDKs and WebRTC server resources.

Conclusion

Vue streaming with Red5 Cloud can be implemented as a focused Vue component: receive connection values, initialize a WHEP subscriber, attach it to a video element, and clean it up when the component or subscription ends. The Red5 Vue repository gives you a working starting point, including WHEP setup, status events, and optional retry behavior.

Top comments (0)