[{"data":1,"prerenderedAt":1027},["ShallowReactive",2],{"content-/ffmpeg-wasm-issue":3,"all-pages-for-dir":1004,"related-/ffmpeg-wasm-issue":1005,"og-image-/ffmpeg-wasm-issue":1026},{"id":4,"title":5,"body":6,"category":989,"concepts":989,"description":990,"extension":991,"meta":992,"navigation":272,"ogImage":989,"path":993,"project_name":989,"published":994,"publishedAt":995,"seo":996,"source":989,"stem":997,"tags":998,"todo":989,"unpublished":994,"updatedAt":995,"__hash__":1003},"pages/2025-12/2025-12-13/ffmpeg-wasm-issue.md","FFmpeg.wasm断念の経緯とWebM出力への切り替え",{"type":7,"value":8,"toc":957},"minimark",[9,13,17,25,28,32,35,38,41,51,54,57,60,73,76,80,182,186,189,195,198,219,222,226,229,232,238,360,364,416,419,422,434,437,448,452,455,472,475,500,503,506,509,513,516,523,527,533,536,554,558,742,863,866,922,926,929,947,950,953],[10,11,5],"h1",{"id":12},"ffmpegwasm断念の経緯とwebm出力への切り替え",[14,15,16],"h2",{"id":16},"概要",[18,19,20,24],"p",{},[21,22,23],"code",{},"proportional-animation-qqq.vue","のアニメーションエクスポート機能において、当初はTwitter投稿に対応するためMP4（H.264）出力を目指していた。しかしFFmpeg.wasmの読み込みで問題が発生しWebM出力に切り替えた。",[14,26,27],{"id":27},"発生した問題",[29,30,31],"h3",{"id":31},"症状",[18,33,34],{},"エクスポートボタンをクリックすると「FFmpegを読み込み中...」で永遠に止まり、処理が進まない。",[29,36,37],{"id":37},"エラーログ",[18,39,40],{},"ブラウザのコンソールとVite開発サーバーに以下の警告が表示された：",[42,43,48],"pre",{"className":44,"code":46,"language":47},[45],"language-text","The file does not exist at \"worker.js?worker_file&type=module\" which is in the optimize deps directory. The dependency might be incompatible with the dep optimizer. Try adding it to optimizeDeps.exclude.\n","text",[21,49,46],{"__ignoreMap":50},"",[29,52,53],{"id":53},"原因",[18,55,56],{},"FFmpeg.wasmは内部でWeb Workerを使用しておりViteの依存関係最適化（optimizeDeps）と互換性がない。",[18,58,59],{},"具体的には：",[61,62,63,67,70],"ol",{},[64,65,66],"li",{},"FFmpeg.wasmはSharedArrayBufferを使用したマルチスレッド処理を行う",[64,68,69],{},"Web Workerファイルを動的にロードしようとする",[64,71,72],{},"Viteのoptimize depsディレクトリ内でworker.jsが見つからず404エラーになる",[14,74,75],{"id":75},"検討した解決策",[29,77,79],{"id":78},"_1-viteの設定変更未実施","1. Viteの設定変更（未実施）",[42,81,85],{"className":82,"code":83,"language":84,"meta":50,"style":50},"language-typescript shiki shiki-themes vitesse-light vitesse-light","// nuxt.config.ts\nexport default defineNuxtConfig({\n  vite: {\n    optimizeDeps: {\n      exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']\n    }\n  }\n})\n","typescript",[21,86,87,96,114,124,132,164,170,176],{"__ignoreMap":50},[88,89,92],"span",{"class":90,"line":91},"line",1,[88,93,95],{"class":94},"sxvE3","// nuxt.config.ts\n",[88,97,99,103,106,110],{"class":90,"line":98},2,[88,100,102],{"class":101},"sHkkW","export",[88,104,105],{"class":101}," default",[88,107,109],{"class":108},"senZ8"," defineNuxtConfig",[88,111,113],{"class":112},"shFtX","({\n",[88,115,117,121],{"class":90,"line":116},3,[88,118,120],{"class":119},"sz8Xr","  vite",[88,122,123],{"class":112},": {\n",[88,125,127,130],{"class":90,"line":126},4,[88,128,129],{"class":119},"    optimizeDeps",[88,131,123],{"class":112},[88,133,135,138,141,145,149,151,154,156,159,161],{"class":90,"line":134},5,[88,136,137],{"class":119},"      exclude",[88,139,140],{"class":112},": [",[88,142,144],{"class":143},"sMJiu","'",[88,146,148],{"class":147},"sdGka","@ffmpeg/ffmpeg",[88,150,144],{"class":143},[88,152,153],{"class":112},", ",[88,155,144],{"class":143},[88,157,158],{"class":147},"@ffmpeg/util",[88,160,144],{"class":143},[88,162,163],{"class":112},"]\n",[88,165,167],{"class":90,"line":166},6,[88,168,169],{"class":112},"    }\n",[88,171,173],{"class":90,"line":172},7,[88,174,175],{"class":112},"  }\n",[88,177,179],{"class":90,"line":178},8,[88,180,181],{"class":112},"})\n",[29,183,185],{"id":184},"_2-coopcoepヘッダーの設定未実施","2. COOP/COEPヘッダーの設定（未実施）",[18,187,188],{},"FFmpeg.wasmはSharedArrayBufferを使用するため、以下のHTTPヘッダーが必要：",[42,190,193],{"className":191,"code":192,"language":47},[45],"Cross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n",[21,194,192],{"__ignoreMap":50},[29,196,197],{"id":197},"断念した理由",[61,199,200,207,213],{},[64,201,202,206],{},[203,204,205],"strong",{},"設定の複雑さ",": nuxt.config.tsの変更、サーバーヘッダーの設定など、複数の変更が必要",[64,208,209,212],{},[203,210,211],{},"副作用のリスク",": COOP/COEPヘッダーは他の機能（外部リソースの読み込みなど）に影響を与える可能性がある",[64,214,215,218],{},[203,216,217],{},"即時性",": 今回は動作確認を優先し、シンプルな解決策を選択",[14,220,221],{"id":221},"採用した解決策",[29,223,225],{"id":224},"webm出力への切り替え","WebM出力への切り替え",[18,227,228],{},"MediaRecorder APIはブラウザネイティブでWebM（VP9）をサポートしているため、FFmpegを経由せずに直接WebMファイルを出力する方式に変更。",[29,230,231],{"id":231},"変更内容",[18,233,234,237],{},[203,235,236],{},"useAnimationExport.ts",":",[42,239,241],{"className":82,"code":240,"language":84,"meta":50,"style":50},"// 変更前\nformat = 'mp4',\n\n// 変更後\nformat = 'webm',\n\n// FFmpeg変換をスキップ\nif (format === 'mp4') {\n  console.warn('MP4出力はFFmpegの設定が必要です。WebMで出力します。')\n}\n",[21,242,243,248,268,274,279,294,298,303,329,354],{"__ignoreMap":50},[88,244,245],{"class":90,"line":91},[88,246,247],{"class":94},"// 変更前\n",[88,249,250,254,257,260,263,265],{"class":90,"line":98},[88,251,253],{"class":252},"s4oTP","format",[88,255,256],{"class":112}," =",[88,258,259],{"class":143}," '",[88,261,262],{"class":147},"mp4",[88,264,144],{"class":143},[88,266,267],{"class":112},",\n",[88,269,270],{"class":90,"line":116},[88,271,273],{"emptyLinePlaceholder":272},true,"\n",[88,275,276],{"class":90,"line":126},[88,277,278],{"class":94},"// 変更後\n",[88,280,281,283,285,287,290,292],{"class":90,"line":134},[88,282,253],{"class":252},[88,284,256],{"class":112},[88,286,259],{"class":143},[88,288,289],{"class":147},"webm",[88,291,144],{"class":143},[88,293,267],{"class":112},[88,295,296],{"class":90,"line":166},[88,297,273],{"emptyLinePlaceholder":272},[88,299,300],{"class":90,"line":172},[88,301,302],{"class":94},"// FFmpeg変換をスキップ\n",[88,304,305,308,311,313,317,319,321,323,326],{"class":90,"line":178},[88,306,307],{"class":101},"if",[88,309,310],{"class":112}," (",[88,312,253],{"class":252},[88,314,316],{"class":315},"stQ0i"," ===",[88,318,259],{"class":143},[88,320,262],{"class":147},[88,322,144],{"class":143},[88,324,325],{"class":112},")",[88,327,328],{"class":112}," {\n",[88,330,332,335,338,341,344,346,349,351],{"class":90,"line":331},9,[88,333,334],{"class":252},"  console",[88,336,337],{"class":112},".",[88,339,340],{"class":108},"warn",[88,342,343],{"class":112},"(",[88,345,144],{"class":143},[88,347,348],{"class":147},"MP4出力はFFmpegの設定が必要です。WebMで出力します。",[88,350,144],{"class":143},[88,352,353],{"class":112},")\n",[88,355,357],{"class":90,"line":356},10,[88,358,359],{"class":112},"}\n",[18,361,362,237],{},[203,363,23],{},[42,365,367],{"className":82,"code":366,"language":84,"meta":50,"style":50},"// 変更前\nformat: 'mp4', // Twitter投稿対応\n\n// 変更後\nformat: 'webm', // WebMで出力（MP4はFFmpeg設定が必要）\n",[21,368,369,373,391,395,399],{"__ignoreMap":50},[88,370,371],{"class":90,"line":91},[88,372,247],{"class":94},[88,374,375,377,379,381,383,385,388],{"class":90,"line":98},[88,376,253],{"class":108},[88,378,237],{"class":112},[88,380,259],{"class":143},[88,382,262],{"class":147},[88,384,144],{"class":143},[88,386,387],{"class":112},",",[88,389,390],{"class":94}," // Twitter投稿対応\n",[88,392,393],{"class":90,"line":116},[88,394,273],{"emptyLinePlaceholder":272},[88,396,397],{"class":90,"line":126},[88,398,278],{"class":94},[88,400,401,403,405,407,409,411,413],{"class":90,"line":134},[88,402,253],{"class":108},[88,404,237],{"class":112},[88,406,259],{"class":143},[88,408,289],{"class":147},[88,410,144],{"class":143},[88,412,387],{"class":112},[88,414,415],{"class":94}," // WebMで出力（MP4はFFmpeg設定が必要）\n",[14,417,418],{"id":418},"トレードオフ",[29,420,421],{"id":421},"メリット",[423,424,425,428,431],"ul",{},[64,426,427],{},"FFmpegの読み込み・変換時間が不要",[64,429,430],{},"追加の設定変更が不要",[64,432,433],{},"エラーなく動作",[29,435,436],{"id":436},"デメリット",[423,438,439,445],{},[64,440,441,444],{},[203,442,443],{},"Twitter非対応",": TwitterはWebMの直接アップロードをサポートしていない",[64,446,447],{},"MP4が必要な場合は外部ツールで変換が必要",[14,449,451],{"id":450},"今後の対応必要な場合","今後の対応（必要な場合）",[18,453,454],{},"MP4出力が必須になった場合、以下の手順で対応：",[61,456,457,463,466,469],{},[64,458,459,462],{},[21,460,461],{},"nuxt.config.ts","にoptimizeDeps.excludeを追加",[64,464,465],{},"サーバーミドルウェアでCOOP/COEPヘッダーを設定",[64,467,468],{},"FFmpeg.wasmの初期化コードを調整",[64,470,471],{},"テスト環境と本番環境の両方で動作確認",[14,473,474],{"id":474},"参考リンク",[423,476,477,486,493],{},[64,478,479],{},[480,481,485],"a",{"href":482,"rel":483},"https://github.com/ffmpegwasm/ffmpeg.wasm",[484],"nofollow","FFmpeg.wasm GitHub",[64,487,488],{},[480,489,492],{"href":490,"rel":491},"https://web.dev/cross-origin-isolation-guide/",[484],"SharedArrayBuffer と Cross-Origin Isolation",[64,494,495],{},[480,496,499],{"href":497,"rel":498},"https://vitejs.dev/config/dep-optimization-options.html",[484],"Vite optimizeDeps",[14,501,502],{"id":502},"結論",[18,504,505],{},"WebM出力は「動く」ことを優先した実用的な選択。Twitter投稿など特定の要件がある場合は、FFmpegの正式対応を検討する。",[507,508],"hr",{},[14,510,512],{"id":511},"補足なぜバックエンドで変換しなかったのか","補足：なぜバックエンドで変換しなかったのか",[29,514,515],{"id":515},"問題の本質",[18,517,518,519,522],{},"今回の問題は",[203,520,521],{},"フロントエンド（ブラウザ内）でFFmpeg.wasmを使おうとしたこと","にある。",[29,524,526],{"id":525},"代替案バックエンドで変換","代替案：バックエンドで変換",[42,528,531],{"className":529,"code":530,"language":47},[45],"[ブラウザ]                    [サーバー]\nWebM生成 → アップロード → ffmpeg変換 → MP4をダウンロード\n",[21,532,530],{"__ignoreMap":50},[18,534,535],{},"バックエンド（Node.js等）なら：",[423,537,538,544,549],{},[64,539,540,543],{},[203,541,542],{},"ネイティブffmpegが使える"," → SharedArrayBuffer不要",[64,545,546],{},[203,547,548],{},"COOP/COEPヘッダー設定不要",[64,550,551],{},[203,552,553],{},"変換も高速",[29,555,557],{"id":556},"実装例概念","実装例（概念）",[42,559,561],{"className":82,"code":560,"language":84,"meta":50,"style":50},"// フロントエンド\nconst webmBlob = await exportAnimation()\nconst formData = new FormData()\nformData.append('video', webmBlob, 'animation.webm')\n\nconst response = await fetch('/api/convert-to-mp4', {\n  method: 'POST',\n  body: formData\n})\nconst mp4Blob = await response.blob()\ndownloadFile(mp4Blob, 'animation.mp4')\n",[21,562,563,568,587,604,638,642,669,686,696,700,721],{"__ignoreMap":50},[88,564,565],{"class":90,"line":91},[88,566,567],{"class":94},"// フロントエンド\n",[88,569,570,573,576,578,581,584],{"class":90,"line":98},[88,571,572],{"class":315},"const ",[88,574,575],{"class":252},"webmBlob",[88,577,256],{"class":112},[88,579,580],{"class":101}," await",[88,582,583],{"class":108}," exportAnimation",[88,585,586],{"class":112},"()\n",[88,588,589,591,594,596,599,602],{"class":90,"line":116},[88,590,572],{"class":315},[88,592,593],{"class":252},"formData",[88,595,256],{"class":112},[88,597,598],{"class":315}," new ",[88,600,601],{"class":108},"FormData",[88,603,586],{"class":112},[88,605,606,608,610,613,615,617,620,622,624,627,629,631,634,636],{"class":90,"line":126},[88,607,593],{"class":252},[88,609,337],{"class":112},[88,611,612],{"class":108},"append",[88,614,343],{"class":112},[88,616,144],{"class":143},[88,618,619],{"class":147},"video",[88,621,144],{"class":143},[88,623,387],{"class":112},[88,625,626],{"class":252}," webmBlob",[88,628,387],{"class":112},[88,630,259],{"class":143},[88,632,633],{"class":147},"animation.webm",[88,635,144],{"class":143},[88,637,353],{"class":112},[88,639,640],{"class":90,"line":134},[88,641,273],{"emptyLinePlaceholder":272},[88,643,644,646,649,651,653,656,658,660,663,665,667],{"class":90,"line":166},[88,645,572],{"class":315},[88,647,648],{"class":252},"response",[88,650,256],{"class":112},[88,652,580],{"class":101},[88,654,655],{"class":108}," fetch",[88,657,343],{"class":112},[88,659,144],{"class":143},[88,661,662],{"class":147},"/api/convert-to-mp4",[88,664,144],{"class":143},[88,666,387],{"class":112},[88,668,328],{"class":112},[88,670,671,674,677,679,682,684],{"class":90,"line":172},[88,672,673],{"class":119},"  method",[88,675,676],{"class":112},": ",[88,678,144],{"class":143},[88,680,681],{"class":147},"POST",[88,683,144],{"class":143},[88,685,267],{"class":112},[88,687,688,691,693],{"class":90,"line":178},[88,689,690],{"class":119},"  body",[88,692,676],{"class":112},[88,694,695],{"class":252},"formData\n",[88,697,698],{"class":90,"line":331},[88,699,181],{"class":112},[88,701,702,704,707,709,711,714,716,719],{"class":90,"line":356},[88,703,572],{"class":315},[88,705,706],{"class":252},"mp4Blob",[88,708,256],{"class":112},[88,710,580],{"class":101},[88,712,713],{"class":252}," response",[88,715,337],{"class":112},[88,717,718],{"class":108},"blob",[88,720,586],{"class":112},[88,722,724,727,729,731,733,735,738,740],{"class":90,"line":723},11,[88,725,726],{"class":108},"downloadFile",[88,728,343],{"class":112},[88,730,706],{"class":252},[88,732,387],{"class":112},[88,734,259],{"class":143},[88,736,737],{"class":147},"animation.mp4",[88,739,144],{"class":143},[88,741,353],{"class":112},[42,743,745],{"className":82,"code":744,"language":84,"meta":50,"style":50},"// バックエンド (Node.js)\nimport ffmpeg from 'fluent-ffmpeg'\n\napp.post('/api/convert-to-mp4', async (req, res) => {\n  ffmpeg(inputPath)\n    .outputFormat('mp4')\n    .pipe(res)\n})\n",[21,746,747,752,771,775,815,827,845,859],{"__ignoreMap":50},[88,748,749],{"class":90,"line":91},[88,750,751],{"class":94},"// バックエンド (Node.js)\n",[88,753,754,757,760,763,765,768],{"class":90,"line":98},[88,755,756],{"class":101},"import",[88,758,759],{"class":252}," ffmpeg",[88,761,762],{"class":101}," from",[88,764,259],{"class":143},[88,766,767],{"class":147},"fluent-ffmpeg",[88,769,770],{"class":143},"'\n",[88,772,773],{"class":90,"line":116},[88,774,273],{"emptyLinePlaceholder":272},[88,776,777,780,782,785,787,789,791,793,795,798,800,803,805,808,810,813],{"class":90,"line":126},[88,778,779],{"class":252},"app",[88,781,337],{"class":112},[88,783,784],{"class":108},"post",[88,786,343],{"class":112},[88,788,144],{"class":143},[88,790,662],{"class":147},[88,792,144],{"class":143},[88,794,387],{"class":112},[88,796,797],{"class":315}," async",[88,799,310],{"class":112},[88,801,802],{"class":252},"req",[88,804,387],{"class":112},[88,806,807],{"class":252}," res",[88,809,325],{"class":112},[88,811,812],{"class":112}," =>",[88,814,328],{"class":112},[88,816,817,820,822,825],{"class":90,"line":134},[88,818,819],{"class":108},"  ffmpeg",[88,821,343],{"class":112},[88,823,824],{"class":252},"inputPath",[88,826,353],{"class":112},[88,828,829,832,835,837,839,841,843],{"class":90,"line":166},[88,830,831],{"class":112},"    .",[88,833,834],{"class":108},"outputFormat",[88,836,343],{"class":112},[88,838,144],{"class":143},[88,840,262],{"class":147},[88,842,144],{"class":143},[88,844,353],{"class":112},[88,846,847,849,852,854,857],{"class":90,"line":172},[88,848,831],{"class":112},[88,850,851],{"class":108},"pipe",[88,853,343],{"class":112},[88,855,856],{"class":252},"res",[88,858,353],{"class":112},[88,860,861],{"class":90,"line":178},[88,862,181],{"class":112},[29,864,865],{"id":865},"方式比較",[867,868,869,885],"table",{},[870,871,872],"thead",{},[873,874,875,879,882],"tr",{},[876,877,878],"th",{},"方式",[876,880,881],{},"難易度",[876,883,884],{},"備考",[886,887,888,900,911],"tbody",{},[873,889,890,894,897],{},[891,892,893],"td",{},"フロントのみ（FFmpeg.wasm）",[891,895,896],{},"高",[891,898,899],{},"ヘッダー設定、Vite互換性問題",[873,901,902,905,908],{},[891,903,904],{},"バックエンドで変換",[891,906,907],{},"低〜中",[891,909,910],{},"Node.js + ffmpegで簡単",[873,912,913,916,919],{},[891,914,915],{},"外部ツールで手動変換",[891,917,918],{},"最も簡単",[891,920,921],{},"UXは劣る",[29,923,925],{"id":924},"cloudflare環境での選択肢","Cloudflare環境での選択肢",[18,927,928],{},"Cloudflare Workersではffmpegは直接使えないため：",[61,930,931,936,942],{},[64,932,933],{},[203,934,935],{},"Cloudflare R2 + 外部変換サービス",[64,937,938,941],{},[203,939,940],{},"Cloudflare Stream","（動画アップロードサービス）",[64,943,944],{},[203,945,946],{},"自前のVPS/EC2でffmpegを動かす",[29,948,949],{"id":949},"今回の判断",[18,951,952],{},"バックエンドAPIを新規構築するコストとWebM出力で十分なユースケース（Discord、YouTube等）を考慮しWebM出力で妥協した。MP4が必須になった場合はバックエンド変換APIの追加を検討する。",[954,955,956],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}",{"title":50,"searchDepth":98,"depth":98,"links":958},[959,960,965,970,974,978,979,980,981],{"id":16,"depth":98,"text":16},{"id":27,"depth":98,"text":27,"children":961},[962,963,964],{"id":31,"depth":116,"text":31},{"id":37,"depth":116,"text":37},{"id":53,"depth":116,"text":53},{"id":75,"depth":98,"text":75,"children":966},[967,968,969],{"id":78,"depth":116,"text":79},{"id":184,"depth":116,"text":185},{"id":197,"depth":116,"text":197},{"id":221,"depth":98,"text":221,"children":971},[972,973],{"id":224,"depth":116,"text":225},{"id":231,"depth":116,"text":231},{"id":418,"depth":98,"text":418,"children":975},[976,977],{"id":421,"depth":116,"text":421},{"id":436,"depth":116,"text":436},{"id":450,"depth":98,"text":451},{"id":474,"depth":98,"text":474},{"id":502,"depth":98,"text":502},{"id":511,"depth":98,"text":512,"children":982},[983,984,985,986,987,988],{"id":515,"depth":116,"text":515},{"id":525,"depth":116,"text":526},{"id":556,"depth":116,"text":557},{"id":865,"depth":116,"text":865},{"id":924,"depth":116,"text":925},{"id":949,"depth":116,"text":949},null,"アニメーションエクスポート機能でFFmpeg.wasmによるMP4変換を断念し、WebM出力に切り替えた理由の記録","md",{},"/ffmpeg-wasm-issue",false,"2025-12-13T00:00:00.000Z",{"title":5,"description":990},"2025-12/2025-12-13/ffmpeg-wasm-issue",[999,289,1000,1001,1002],"ffmpeg","vite","troubleshooting","technical-decision","hr9NESXognUCkeUk2oJ0YI0525A7vvWCkL2p1fbFDuQ",[],[1006,1010,1014,1018,1022],{"title":1007,"path":1008,"publishedAt":1009},"Claude Code のフック音声・Codex GPT-5.5 ロールアウト・ffmpeg NVENC 廃止オプションのトラブル対応","/env-troubles-sound-gpt55-nvenc","2026-04-24T00:00:00.000Z",{"title":1011,"path":1012,"publishedAt":1013},"開発環境のバックアップを仕上げ、復旧手順をスキル化してGitHubで版管理する","/claude-env-backup-and-restore-skill","2026-07-30T00:00:00.000Z",{"title":1015,"path":1016,"publishedAt":1017},"決算ビートモニタリングを13→20銘柄へ拡張し、3区分の親子構造へ作り替えた","/beat-monitoring-ticker-expansion","2026-05-29T00:00:00.000Z",{"title":1019,"path":1020,"publishedAt":1021},"Twitter動画のGemini用400MB分割スクリプト - bat＋PowerShellランチャー方式","/twitter-video-split-for-gemini","2026-04-16T00:00:00.000Z",{"title":1023,"path":1024,"publishedAt":1025},"ナレーションコンテンツ改善とNarrationViewer拡張 - レビュー・音声・テスト・動画レンダリング","/narration-viewer-improvements","2026-03-16T00:00:00.000Z","https://log.eurekapu.com/og/blog/ffmpeg-wasm-issue.png?v=2025-12-13T00%3A00%3A00.000Z&title=FFmpeg.wasm%E6%96%AD%E5%BF%B5%E3%81%AE%E7%B5%8C%E7%B7%AF%E3%81%A8WebM%E5%87%BA%E5%8A%9B%E3%81%B8%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88&author=Kei%20Komatsu&sig=7cf38f55199806cd",1785654677200]