import { AudioCodec, MediaContainer, VideoCodec } from "./types"; export function decodePath(path: string) { return path .split("/") .map((segment) => decodeURIComponent(segment)) .join("/"); } export function encodePath(path: string) { return path .split("/") .map((segment) => encodeURIComponent(segment)) .join("/"); } //IMPORTANT: needs to be kept in sync with the backend ffmpeg parameters export function createRFC6381String(container: MediaContainer, videoCodec: VideoCodec, audioCodec: AudioCodec): string { let mimeType = ""; switch (container) { case MediaContainer.mp4: mimeType = "video/mp4"; break; case MediaContainer.webm: mimeType = "video/webm"; break; case MediaContainer.mp3: mimeType = "audio/mpeg"; break; case MediaContainer.ogg: mimeType = "audio/ogg"; break; default: throw new Error(`Unsupported container: ${container}`); } mimeType += '; codecs="'; //TODO: use correct level values switch (videoCodec) { case VideoCodec.none: break; case VideoCodec.av1: mimeType += "av01.0.17M.08, "; // Main profile, level 6.1, Main tier, 8bit break; case VideoCodec.h264: mimeType += "avc1.64003d, "; // High Profile (profile number + constraint flags), level 6.1 break; case VideoCodec.h265: mimeType += "hev1.1.1.L183, "; // Main profile, Main tier, level 6.1 break; case VideoCodec.vp9: mimeType += "vp09.00.61.08, "; //4:2:0, level 6.1, 8bit break; default: throw new Error(`Unsupported video codec: ${videoCodec}`); } switch (audioCodec) { case AudioCodec.opus: mimeType += "opus"; break; case AudioCodec.aac: mimeType += "aac"; break; case AudioCodec.vorbis: mimeType += "vorbis"; break; case AudioCodec.mp3: mimeType += "mp3"; break; default: throw new Error(`Unsupported audio codec: ${audioCodec}`); } mimeType += '"'; return mimeType; }