UNPKG

webcodecs-encoder

Version:

A TypeScript library for browser environments to encode video (H.264/AVC, VP9, VP8) and audio (AAC, Opus) using the WebCodecs API and mux them into MP4 or WebM containers with real-time streaming support. New function-first API design.

1 lines 13.4 kB
{"version":3,"sources":["../../src/utils/can-encode.ts"],"sourcesContent":["/**\n * エンコード可能性の検証\n */\n\nimport { EncodeOptions, VideoConfig, AudioConfig } from \"../types\";\n\n/**\n * エンコード可能性の検証\n *\n * @param options エンコードオプション\n * @returns エンコード可能かどうか\n */\nexport async function canEncode(options?: EncodeOptions): Promise<boolean> {\n try {\n // WebCodecsの基本サポート確認\n if (!isWebCodecsSupported()) {\n return false;\n }\n\n // デフォルト設定でのテスト\n if (!options) {\n return await testDefaultConfiguration();\n }\n\n // ビデオ設定の確認(ビデオが指定されている場合のみ)\n const hasVideoConfig = options.video && typeof options.video === \"object\";\n const hasVideo = hasVideoConfig || !options.audio;\n if (hasVideo) {\n const videoCodec = hasVideoConfig\n ? (options.video as VideoConfig).codec || \"avc\"\n : \"avc\";\n const videoSupported = await testVideoCodecSupport(videoCodec, options);\n if (!videoSupported) {\n return false;\n }\n }\n\n // オーディオ設定の確認(オーディオが明示的に指定されている場合のみ)\n const hasAudioConfig = options.audio && typeof options.audio === \"object\";\n if (hasAudioConfig) {\n const audioCodec = (options.audio as AudioConfig).codec || \"aac\";\n const audioSupported = await testAudioCodecSupport(audioCodec, options);\n if (!audioSupported) {\n return false;\n }\n } else if (options.audio === undefined && !hasVideoConfig) {\n // デフォルト設定の場合のみオーディオもチェック\n const audioSupported = await testAudioCodecSupport(\"aac\", options);\n if (!audioSupported) {\n return false;\n }\n }\n\n return true;\n } catch (error) {\n // エラーが発生した場合は対応していないと判断\n console.warn(\"canEncode error:\", error);\n return false;\n }\n}\n\n/**\n * WebCodecsの基本サポートを確認\n */\nfunction isWebCodecsSupported(): boolean {\n try {\n return (\n typeof VideoEncoder !== \"undefined\" &&\n typeof AudioEncoder !== \"undefined\" &&\n typeof VideoFrame !== \"undefined\" &&\n typeof AudioData !== \"undefined\"\n );\n } catch {\n return false;\n }\n}\n\n/**\n * デフォルト設定でのエンコード可能性を確認\n */\nasync function testDefaultConfiguration(): Promise<boolean> {\n try {\n const defaultWidth = 640;\n const defaultHeight = 480;\n const defaultFrameRate = 30;\n\n // H.264 (AVC) のテスト\n const videoConfig: VideoEncoderConfig = {\n codec: generateAvcCodecString(\n defaultWidth,\n defaultHeight,\n defaultFrameRate,\n ),\n width: defaultWidth,\n height: defaultHeight,\n bitrate: 1_000_000,\n framerate: defaultFrameRate,\n };\n\n const videoSupport = await VideoEncoder.isConfigSupported(videoConfig);\n if (!videoSupport.supported) {\n return false;\n }\n\n // AAC のテスト\n const audioConfig: AudioEncoderConfig = {\n codec: \"mp4a.40.2\", // AAC-LC\n sampleRate: 48000,\n numberOfChannels: 2,\n bitrate: 128_000,\n };\n\n const audioSupport = await AudioEncoder.isConfigSupported(audioConfig);\n return audioSupport.supported || false;\n } catch {\n return false;\n }\n}\n\n/**\n * ビデオコーデックのサポートを確認\n */\nasync function testVideoCodecSupport(\n codec: string,\n options?: EncodeOptions,\n): Promise<boolean> {\n try {\n const codecString = getVideoCodecString(\n codec,\n options?.width || 640,\n options?.height || 480,\n options?.frameRate || 30,\n );\n const config: VideoEncoderConfig = {\n codec: codecString,\n width: options?.width || 640,\n height: options?.height || 480,\n bitrate:\n options?.video === false\n ? 0\n : (options?.video as any)?.bitrate || 1_000_000,\n framerate: options?.frameRate || 30,\n };\n\n // オプションの詳細設定を追加\n if (\n options &&\n options.video !== false &&\n (options.video as any)?.hardwareAcceleration\n ) {\n config.hardwareAcceleration = (options.video as any).hardwareAcceleration;\n }\n\n if (\n options &&\n options.video !== false &&\n (options.video as any)?.latencyMode\n ) {\n config.latencyMode = (options.video as any).latencyMode;\n }\n\n const support = await VideoEncoder.isConfigSupported(config);\n return support.supported || false;\n } catch {\n return false;\n }\n}\n\n/**\n * オーディオコーデックのサポートを確認\n */\nasync function testAudioCodecSupport(\n codec: string,\n options?: EncodeOptions,\n): Promise<boolean> {\n try {\n const codecString = getAudioCodecString(codec);\n const audioOptions =\n typeof options?.audio === \"object\" ? options.audio : {};\n\n const config: AudioEncoderConfig = {\n codec: codecString,\n sampleRate: audioOptions.sampleRate || 48000,\n numberOfChannels: audioOptions.channels || 2,\n bitrate: audioOptions.bitrate || 128_000,\n };\n\n // AACの場合、bitrateMode設定を追加\n if (codec === \"aac\" && audioOptions.bitrateMode) {\n (config as any).bitrateMode = audioOptions.bitrateMode;\n }\n\n const support = await AudioEncoder.isConfigSupported(config);\n return support.supported || false;\n } catch {\n return false;\n }\n}\n\n/**\n * ビデオコーデック名をWebCodecs用の文字列に変換\n */\nfunction getVideoCodecString(\n codec: string,\n width = 640,\n height = 480,\n frameRate = 30,\n): string {\n switch (codec) {\n case \"avc\":\n return generateAvcCodecString(width, height, frameRate);\n case \"hevc\":\n return \"hev1.1.6.L93.B0\"; // H.265 Main Profile\n case \"vp9\":\n return \"vp09.00.10.08\"; // VP9 Profile 0\n case \"vp8\":\n return \"vp8\"; // VP8\n case \"av1\":\n return \"av01.0.04M.08\"; // AV1 Main Profile Level 4.0\n default:\n return codec; // そのまま返す(カスタムコーデック文字列の場合)\n }\n}\n\n/**\n * AVC (H.264) コーデック文字列を動的に生成\n * encoder-worker.tsと同じロジックを使用\n */\nfunction generateAvcCodecString(\n width: number,\n height: number,\n frameRate: number,\n profile?: \"high\" | \"main\" | \"baseline\",\n): string {\n const mbPerSec = Math.ceil(width / 16) * Math.ceil(height / 16) * frameRate;\n let level: number;\n if (mbPerSec <= 108000) level = 31;\n else if (mbPerSec <= 216000) level = 32;\n else if (mbPerSec <= 245760) level = 40;\n else if (mbPerSec <= 589824) level = 50;\n else if (mbPerSec <= 983040) level = 51;\n else level = 52;\n\n const chosenProfile =\n profile ?? (width >= 1280 || height >= 720 ? \"high\" : \"baseline\");\n const profileHex =\n chosenProfile === \"high\" ? \"64\" : chosenProfile === \"main\" ? \"4d\" : \"42\";\n const levelHex = level.toString(16).padStart(2, \"0\");\n\n return `avc1.${profileHex}00${levelHex}`;\n}\n\n/**\n * オーディオコーデック名をWebCodecs用の文字列に変換\n */\nfunction getAudioCodecString(codec: string): string {\n switch (codec) {\n case \"aac\":\n return \"mp4a.40.2\"; // AAC-LC\n case \"opus\":\n return \"opus\"; // Opus\n default:\n return codec; // そのまま返す(カスタムコーデック文字列の場合)\n }\n}\n\n/**\n * 特定のコーデックとプロファイルでのサポート確認(上級者向け)\n */\nexport async function canEncodeWithProfile(\n videoCodec: string,\n audioCodec?: string,\n profile?: {\n width: number;\n height: number;\n framerate: number;\n videoBitrate: number;\n audioBitrate?: number;\n },\n): Promise<{ video: boolean; audio: boolean; overall: boolean }> {\n const result = { video: false, audio: false, overall: false };\n\n try {\n // ビデオの確認\n if (videoCodec) {\n const videoConfig: VideoEncoderConfig = {\n codec: getVideoCodecString(videoCodec),\n width: profile?.width || 1920,\n height: profile?.height || 1080,\n bitrate: profile?.videoBitrate || 2_000_000,\n framerate: profile?.framerate || 30,\n };\n\n const videoSupport = await VideoEncoder.isConfigSupported(videoConfig);\n result.video = videoSupport.supported || false;\n }\n\n // オーディオの確認\n if (audioCodec) {\n const audioConfig: AudioEncoderConfig = {\n codec: getAudioCodecString(audioCodec),\n sampleRate: 48000,\n numberOfChannels: 2,\n bitrate: profile?.audioBitrate || 128_000,\n };\n\n const audioSupport = await AudioEncoder.isConfigSupported(audioConfig);\n result.audio = audioSupport.supported || false;\n } else {\n result.audio = true; // オーディオなしの場合は対応とみなす\n }\n\n result.overall = result.video && result.audio;\n return result;\n } catch (error) {\n console.warn(\"canEncodeWithProfile error:\", error);\n return result;\n }\n}\n"],"mappings":"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","names":[]}