107 lines
3.3 KiB
TypeScript
107 lines
3.3 KiB
TypeScript
/** Where a channel can stream to, and what each platform needs. */
|
|
export interface Platform {
|
|
id: string;
|
|
label: string;
|
|
/** Default ingest server; empty means the platform gives you one per stream. */
|
|
ingest: string;
|
|
/** Where to find the stream key. */
|
|
keyHelp: string;
|
|
/** Shown 9:16 on phones: use a portrait channel. */
|
|
vertical: boolean;
|
|
/** How the platform keeps the recording. */
|
|
vods: string;
|
|
/** Brand color, for its badge. */
|
|
color: string;
|
|
}
|
|
|
|
export const PLATFORMS: Platform[] = [
|
|
{
|
|
id: 'twitch',
|
|
label: 'Twitch',
|
|
color: '#9146FF',
|
|
ingest: 'rtmp://ingest.global-contribute.live-video.net/app',
|
|
keyHelp: 'Twitch Creator Dashboard → Settings → Stream → Primary stream key.',
|
|
vertical: false,
|
|
vods: 'Turn on “Store past broadcasts” in Twitch → Settings → Stream. Twitch keeps them 7 days, or 60 for Partners, Turbo and Prime.'
|
|
},
|
|
{
|
|
id: 'youtube',
|
|
label: 'YouTube',
|
|
color: '#FF0033',
|
|
ingest: 'rtmps://a.rtmps.youtube.com/live2',
|
|
keyHelp:
|
|
'YouTube Studio → Create → Go live → Stream → Stream key. A persistent key works for every stream.',
|
|
vertical: false,
|
|
vods: 'YouTube keeps every stream as a video on the channel by itself.'
|
|
},
|
|
{
|
|
id: 'facebook',
|
|
label: 'Facebook',
|
|
color: '#1877F2',
|
|
ingest: 'rtmps://live-api-s.facebook.com:443/rtmp',
|
|
keyHelp: 'Facebook Live Producer → Streaming software → “Use a persistent stream key”.',
|
|
vertical: false,
|
|
vods: 'Facebook posts the stream as a video when it ends.'
|
|
},
|
|
{
|
|
id: 'x',
|
|
label: 'X (Twitter)',
|
|
color: '#e7e9ea',
|
|
ingest: '',
|
|
keyHelp: 'X Media Studio → Producer → Sources: copy the RTMP URL and the stream key.',
|
|
vertical: false,
|
|
vods: 'X keeps the broadcast as a post.'
|
|
},
|
|
{
|
|
id: 'instagram',
|
|
label: 'Instagram',
|
|
color: '#E1306C',
|
|
ingest: '',
|
|
keyHelp:
|
|
'instagram.com → Create → Live video: copy the stream URL and key. Instagram makes a new key for every broadcast.',
|
|
vertical: true,
|
|
vods: 'Share the live video to your profile when it ends.'
|
|
},
|
|
{
|
|
id: 'tiktok',
|
|
label: 'TikTok',
|
|
color: '#25F4EE',
|
|
ingest: '',
|
|
keyHelp:
|
|
'TikTok LIVE Center (or LIVE Studio) → Stream key: copy the server URL and key. Needs an account that can go LIVE.',
|
|
vertical: true,
|
|
vods: 'TikTok offers a replay for a while after the stream.'
|
|
},
|
|
{
|
|
id: 'custom',
|
|
label: 'Other RTMP server',
|
|
color: '#a1a1aa',
|
|
ingest: '',
|
|
keyHelp: 'Any RTMP or RTMPS server: its URL, and the stream key if it has one.',
|
|
vertical: false,
|
|
vods: 'Up to the server.'
|
|
}
|
|
];
|
|
|
|
export const platform = (id: string) =>
|
|
PLATFORMS.find((each) => each.id === id) ?? PLATFORMS[PLATFORMS.length - 1];
|
|
|
|
export const QUALITIES: Record<
|
|
string,
|
|
{ label: string; height: number; fps: number; bitrate: number }
|
|
> = {
|
|
'720p30': { label: '720p, 30 fps (3 Mbps)', height: 720, fps: 30, bitrate: 3000 },
|
|
'1080p30': { label: '1080p, 30 fps (4.5 Mbps)', height: 1080, fps: 30, bitrate: 4500 },
|
|
'1080p60': { label: '1080p, 60 fps (6 Mbps)', height: 1080, fps: 60, bitrate: 6000 }
|
|
};
|
|
|
|
/** Output size for a channel: 16:9, or 9:16 for portrait. */
|
|
export function outputSize(format: string, quality: string) {
|
|
const q = QUALITIES[quality] ?? QUALITIES['1080p30'];
|
|
const long = Math.round((q.height * 16) / 9);
|
|
const { height: short, ...rest } = q;
|
|
return format === 'portrait'
|
|
? { ...rest, width: short, height: long }
|
|
: { ...rest, width: long, height: short };
|
|
}
|