( mimeType: string, hasAudio: boolean, )
| 221 | // Chromebooks) would otherwise be mislabelled, and an mp4 fallback carries aac, |
| 222 | // not opus. |
| 223 | export const describeRecordingCodecs = ( |
| 224 | mimeType: string, |
| 225 | hasAudio: boolean, |
| 226 | ): { videoCodec: string; audioCodec: string | undefined } => { |
| 227 | const lowerType = mimeType.toLowerCase(); |
| 228 | const codecsMatch = lowerType.match(/codecs\s*=\s*"?([^"]+)"?/); |
| 229 | const codecs = (codecsMatch?.[1] ?? "") |
| 230 | .split(",") |
| 231 | .map((codec) => codec.trim()) |
| 232 | .filter(Boolean); |
| 233 | const isWebm = lowerType.includes("webm"); |
| 234 | const hasCodec = (prefix: string) => |
| 235 | codecs.some((codec) => codec.startsWith(prefix)); |
| 236 | |
| 237 | let videoCodec: string; |
| 238 | if (hasCodec("vp9")) videoCodec = "vp9"; |
| 239 | else if (hasCodec("vp8")) videoCodec = "vp8"; |
| 240 | else if (hasCodec("avc1") || hasCodec("h264")) videoCodec = "h264"; |
| 241 | else videoCodec = isWebm ? "vp8" : "h264"; |
| 242 | |
| 243 | if (!hasAudio) { |
| 244 | return { videoCodec, audioCodec: undefined }; |
| 245 | } |
| 246 | |
| 247 | let audioCodec: string; |
| 248 | if (hasCodec("opus")) audioCodec = "opus"; |
| 249 | else if (hasCodec("mp4a") || hasCodec("aac")) audioCodec = "aac"; |
| 250 | else audioCodec = isWebm ? "opus" : "aac"; |
| 251 | |
| 252 | return { videoCodec, audioCodec }; |
| 253 | }; |
| 254 | |
| 255 | export const isUserCancellationError = (error: unknown): boolean => { |
| 256 | if (!(error instanceof DOMException)) return false; |
no test coverage detected