This example builds directly on the basic WHIPClient publish flow and adds codec selection controls before publish starts.
At a high level:
- create a
WHIPClient - provide a "preview" of media to be streamed
- discover browser-supported codecs
- filter that list to codecs the SDK can request
- pass selected
videoEncodingandaudioEncodinginto publisher initialization - publish normally
- Utilizing the generated MediaStream in preview for streaming
- WHIP publishing with explicit codec preference hints
- dynamic codec option generation from browser + SDK support overlap
- graceful fallback to default codec behavior when no explicit codec is selected
- the same start/stop/event lifecycle used by the basic publisher examples
The browser may report codecs that are not valid choices for the Red5 Pro publish encoder enums, and the SDK enums can contain values the current browser does not support.
This example avoids invalid combinations by intersecting both sources:
- Browser capability source:
RTCRtpSender.getCapabilities('video' | 'audio') - SDK publish enums:
PublishVideoEncoderandPublishAudioEncoder
Only codec names present in both are shown to the user.
The snippet below is intentionally simplified for learning and does not include every helper used in the testbed:
// If integrating as a script dependency from a CDN:
const sdk = window.red5prosdk
const { WHIPClient, PublishVideoEncoder, PublishAudioEncoder } = sdk
// OR, If integrating as a module from NPM install:
// import { WHIPClient, PublishVideoEncoder, PublishAudioEncoder } from 'red5pro-webrtc-sdk'
function getSupportedCodecNames(kind: 'audio' | 'video'): string[] {
if (!RTCRtpSender?.getCapabilities) return []
const caps = RTCRtpSender.getCapabilities(kind)
if (!caps) return []
const encoderEnum = kind === 'video' ? PublishVideoEncoder : PublishAudioEncoder
return [
...new Set(
caps.codecs
.map((codec) => codec.mimeType.split('/')[1]?.toUpperCase())
.filter((name): name is string => Boolean(name) && name in encoderEnum)
),
].sort()
}
const selectedVideo = 'H264' // from UI select, or "default"
const selectedAudio = 'OPUS' // from UI select, or "default"
const videoEncoding =
selectedVideo === 'default'
? undefined
: PublishVideoEncoder[selectedVideo as keyof typeof PublishVideoEncoder]
const audioEncoding =
selectedAudio === 'default'
? undefined
: PublishAudioEncoder[selectedAudio as keyof typeof PublishAudioEncoder]
const publisher = new WHIPClient()
await publisher.initWithStream(
{
endpoint,
streamName,
mediaElementId: 'publisher-video',
connectionParams,
videoEncoding,
audioEncoding,
},
mediaStream
)
await publisher.publish()Use this sequence in your own webapp:
- Build your normal WHIP publish form (
streamName, host/endpoint settings, media selection). - Add video/audio codec
<select>controls with adefaultoption. - On load, compute codec options from browser capabilities and filter against SDK publish enums.
- On publish click, resolve selected strings to SDK enum values.
- Pass
videoEncodingandaudioEncodingin yourWHIPClientinit config. - Keep
undefinedfor either field when you want automatic browser/server negotiation.
Codec preferences are independent from deployment mode. The endpoint and connection parameter setup is still the same pattern as other WHIP examples.
endpointtargets the server directly (origin).connectionParamsis optional unless your server/plugins require extra values (for example authentication credentials).
Example shape:
const endpoint = `https://${host}:443/live/whip/${streamName}`
const connectionParams = {
// optional plugin/query params
}endpointshould target Stream Manager proxy routing (not a hardcoded origin/edge).connectionParamsis where Stream Manager-related values (region/nodeGroup/transcoder/auth metadata) are commonly supplied.
Example shape:
const endpoint = `https://${host}/as/v1/proxy/whip/${app}/${streamName}`
const connectionParams = {
// e.g. region, nodeGroup, strict matching flags, authentication credentials, etc.
}- codec option initialization:
initCodecSelects() - codec discovery/filtering helpers:
getUniqueCodecListing()insrc/lib/codec-preferences.ts - publish codec resolution:
resolvePublishVideoEncoding()/resolvePublishAudioEncoding() - publish flow:
startPublish() - stop flow:
stopPublish() - event handling:
onPublisherEvent()
Pair this with whep-codec-preference to explain codec preference behavior on subscribe/playback.