Live Transcoding
For media servers that transcode video on demand rather than serving pre-encoded HLS.
LiveTranscodingPlugin manages the negotiation with a NoMercy media server endpoint, monitors transcode progress, and exposes quality switching that works alongside the server’s encoding pipeline.
Prerequisites: Video Quick Start. Your server must expose a compatible /transcode endpoint.
Minimal setup
import { nmplayer } from '@nomercy-entertainment/nomercy-video-player';
import { DesktopUiPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
import { LiveTranscodingPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins';
const player = nmplayer('main')
.addPlugin(DesktopUiPlugin)
.addPlugin(LiveTranscodingPlugin, {
controlUrl: 'wss://media.your-server.com/transcode/movie-1/ws',
seekTimeoutMs: 15_000,
})
.setup({
baseUrl: 'https://media.your-server.com',
auth: { bearerToken: () => myAuth.getToken() },
playlist: [
{
id: 'movie-1',
title: 'My Movie',
url: '/api/transcode/movie-1/stream.m3u8',
duration: 7200,
},
],
});
player.on('ready', () => {
player.item(0, { autoplay: true });
});
The plugin opens a control WebSocket to controlUrl and listens for transcode-progress messages from the server.
When the server is still encoding, it gates beforeLoad and beforeSeek until the transcoder has reached the requested position, so playback never outruns the encode.
Monitoring transcode progress
const transcodingPlugin = player.getPlugin(LiveTranscodingPlugin);
// Fires on each progress update from the server:
player.on('plugin:live-transcoding:job:progress', ({ transcodedSeconds, totalSeconds }) => {
if (totalSeconds) {
progressBar.value = transcodedSeconds / totalSeconds;
}
progressLabel.textContent = `Encoding: ${Math.floor(transcodedSeconds)}s`;
});
// Fires when the full transcode job completes:
player.on('plugin:live-transcoding:job:complete', ({ jobId }) => {
progressBar.hidden = true;
});
// Fires if the server reports an error:
player.on('plugin:live-transcoding:job:error', ({ error }) => {
showError(error.message);
});
Quality hint
Pass preferredHeight to request a target output height from the transcoding server:
player.addPlugin(LiveTranscodingPlugin, {
controlUrl: 'wss://media.your-server.com/transcode/movie-1/ws',
preferredHeight: 1080,
});
When the server is encoding multiple quality variants in parallel, the player’s standard player.quality(idx) call controls which HLS level hls.js selects, and standard ABR applies once variants are available.
Session cleanup
The transcode session on the server holds resources (CPU, disk).
Disposing the player closes the plugin’s control WebSocket (the channel auto-closes on dispose), which is the server’s signal to tear the session down:
// On page unload or player unmount:
player.dispose(); // closes the control WebSocket; the server tears down the session on disconnect
For single-page apps, wire disposal to your router’s leave hook:
// Vue Router:
onBeforeRouteLeave(() => {
player.dispose();
});
// React Router:
useEffect(() => {
return () => player.dispose();
}, []);
What to read next
- Plugins: Live Transcoding, full plugin option and event reference
- HLS, ABR and quality level internals
- Core: Auth & Fetch, securing transcode session requests