[{"data":1,"prerenderedAt":503},["ShallowReactive",2],{"content-/twitter-video-split-for-gemini":3,"all-pages-for-dir":501,"og-image-/twitter-video-split-for-gemini":502},{"id":4,"title":5,"body":6,"category":482,"description":483,"extension":484,"meta":485,"navigation":299,"path":486,"project_name":487,"published":488,"publishedAt":489,"seo":490,"stem":491,"tags":492,"todo":499,"unpublished":488,"updatedAt":499,"__hash__":500},"pages/2026-04/2026-04-16/twitter-video-split-for-gemini.md","Twitter動画のGemini用400MB分割スクリプト - bat＋PowerShellランチャー方式",{"type":7,"value":8,"toc":469},"minimark",[9,14,18,21,27,30,33,44,47,51,58,61,67,77,81,84,87,107,110,137,140,144,147,152,155,161,164,171,211,214,222,225,234,237,243,274,280,316,319,323,326,335,342,345,386,393,397,400,406,409,416,419,423,426,455,462,465],[10,11,13],"h2",{"id":12},"発端-geminiが400mb超の動画を飲み込まない","発端: Geminiが400MB超の動画を飲み込まない",[15,16,17],"p",{},"Twitterから英語動画をダウンロードして、Google AI StudioのGeminiに放り込んで字幕を生成する運用をしている。動画を渡すと文字起こし＋英訳までまとめて返してくれるので、英語学習の素材づくりに重宝している。",[15,19,20],{},"ところが今朝、Dwarkesh Patelのインタビュー動画（約890MB）をアップロードしようとしたら、赤字のバリデーションエラーが返ってきた。",[22,23,24],"blockquote",{},[15,25,26],{},"Video file size cannot exceed 400MB.",[15,28,29],{},"400MB制限。2時間超えのポッドキャスト動画だと簡単に超える。毎回手動でffmpegを叩くのも面倒なので、ドラッグ＆ドロップで3分割してくれるスクリプトを作ることにした。",[15,31,32],{},"対象ファイルのパスがこれ。",[34,35,40],"pre",{"className":36,"code":38,"language":39},[37],"language-text","G:\\マイドライブ\\twitter_download\\20260416_Dwarkesh Patel_2044442721570439168.mp4\n","text",[41,42,38],"code",{"__ignoreMap":43},"",[15,45,46],{},"Googleドライブのマイドライブ直下、半角スペース入り、日本語フォルダ名。Windowsでスクリプト書くときに罠が全部乗っているパスだ。",[10,48,50],{"id":49},"第一弾-素直にbatファイルで書いたら文字化けした","第一弾: 素直にbatファイルで書いたら文字化けした",[15,52,53,54,57],{},"最初はシンプルに考えた。ffmpegはPATHに通してあるし、batファイルにドラッグ＆ドロップすれば",[41,55,56],{},"%1","でパスが拾える。日本語のメッセージをechoしつつ3分割すれば終わり、のはずだった。",[15,59,60],{},"Git Bashからテスト実行した瞬間、コンソールが化けた。",[34,62,65],{"className":63,"code":64,"language":39},[37],"陦悟勁...\n蛻・牡荳ｭ...\n",[41,66,64],{"__ignoreMap":43},[15,68,69,72,73,76],{},[41,70,71],{},"chcp 65001","でUTF-8に切り替えても、",[41,74,75],{},"for /f","と日本語パスの組み合わせで今度はパスが壊れる。batファイルのエンコーディングとcmd.exeのコードページの相性は、いつ触っても心が折れる。",[10,78,80],{"id":79},"方針転換-batはランチャーpowershellで本番ロジック","方針転換: batはランチャー、PowerShellで本番ロジック",[15,82,83],{},"batファイルでロジックを書くのはやめた。ただしドラッグ＆ドロップの受け口としてのbatファイルは捨てがたい。PowerShellスクリプト（.ps1）に直接ファイルをドロップする運用は、セキュリティ設定の絡みで素直に動かないことが多いからだ。",[15,85,86],{},"役割分担をこう決めた。",[88,89,90,101],"ul",{},[91,92,93,97,98,100],"li",{},[94,95,96],"strong",{},"batファイル",": 英語メッセージだけ。",[41,99,56],{},"で受け取ったパスをPowerShellに渡すランチャー",[91,102,103,106],{},[94,104,105],{},"PowerShellスクリプト",": 動画分割の実ロジック。日本語メッセージもここで出す",[15,108,109],{},"batから呼ぶときはこう。",[34,111,115],{"className":112,"code":113,"language":114,"meta":43,"style":43},"language-bat shiki shiki-themes vitesse-light vitesse-light","@echo off\npowershell -NoProfile -ExecutionPolicy Bypass -File \"%~dp0split-video.ps1\" -InputFile \"%~1\"\npause\n","bat",[41,116,117,125,131],{"__ignoreMap":43},[118,119,122],"span",{"class":120,"line":121},"line",1,[118,123,124],{},"@echo off\n",[118,126,128],{"class":120,"line":127},2,[118,129,130],{},"powershell -NoProfile -ExecutionPolicy Bypass -File \"%~dp0split-video.ps1\" -InputFile \"%~1\"\n",[118,132,134],{"class":120,"line":133},3,[118,135,136],{},"pause\n",[15,138,139],{},"batには日本語を一切書かないので、Shift-JISとUTF-8のどちらで保存されても文字化けが起きない。メッセージは全部PowerShell側に寄せる。",[10,141,143],{"id":142},"powershellスクリプトのハマりどころ","PowerShellスクリプトのハマりどころ",[15,145,146],{},"ここから先が本番だった。PowerShellに移しても、罠が3つ連続で待っていた。",[148,149,151],"h3",{"id":150},"罠1-bomなしutf-8だとパースが壊れる","罠1: BOMなしUTF-8だとパースが壊れる",[15,153,154],{},"最初、VS CodeのデフォルトであるBOMなしUTF-8で保存してスクリプトを実行したら、こんなエラーが出た。",[34,156,159],{"className":157,"code":158,"language":39},[37],"トークン 'xxx' は、式またはステートメントで有効な部分ではありません。\n",[41,160,158],{"__ignoreMap":43},[15,162,163],{},"PowerShell 5.1（Windows標準）は、BOMなしUTF-8のマルチバイト文字を正しく解釈してくれない。コメントや文字列リテラルに日本語が入っていると、パーサが途中でコケる。",[15,165,166,167,170],{},"解決策はシンプルで、",[94,168,169],{},"BOM付きUTF-8で保存し直す","だけ。PowerShellからなら1行で変換できる。",[34,172,176],{"className":173,"code":174,"language":175,"meta":43,"style":43},"language-powershell shiki shiki-themes vitesse-light vitesse-light","$content = Get-Content -Path \"split-video.ps1\" -Raw -Encoding UTF8\n[System.IO.File]::WriteAllText(\n    \"split-video.ps1\",\n    $content,\n    [System.Text.UTF8Encoding]::new($true)  # $true = BOM付き\n)\n","powershell",[41,177,178,183,188,193,199,205],{"__ignoreMap":43},[118,179,180],{"class":120,"line":121},[118,181,182],{},"$content = Get-Content -Path \"split-video.ps1\" -Raw -Encoding UTF8\n",[118,184,185],{"class":120,"line":127},[118,186,187],{},"[System.IO.File]::WriteAllText(\n",[118,189,190],{"class":120,"line":133},[118,191,192],{},"    \"split-video.ps1\",\n",[118,194,196],{"class":120,"line":195},4,[118,197,198],{},"    $content,\n",[118,200,202],{"class":120,"line":201},5,[118,203,204],{},"    [System.Text.UTF8Encoding]::new($true)  # $true = BOM付き\n",[118,206,208],{"class":120,"line":207},6,[118,209,210],{},")\n",[15,212,213],{},"VS Codeでも右下のエンコーディング表示をクリックして「Save with Encoding」→「UTF-8 with BOM」で変えられる。Windows専用のPowerShellスクリプトを書くときは、BOM付きを常用するのが安全だ。",[148,215,217,218,221],{"id":216},"罠2-0-mb-のmbが数値サフィックスとして食われる","罠2: ",[41,219,220],{},"\"{0} MB\""," のMBが数値サフィックスとして食われる",[15,223,224],{},"ファイルサイズを表示するコードでこう書いた。",[34,226,228],{"className":173,"code":227,"language":175,"meta":43,"style":43},"Write-Host (\"サイズ: {0:N1} MB\" -f ($size / 1MB))\n",[41,229,230],{"__ignoreMap":43},[118,231,232],{"class":120,"line":121},[118,233,227],{},[15,235,236],{},"これを実行すると、エラーが出る。",[34,238,241],{"className":239,"code":240,"language":39},[37],"式またはステートメントにキャストできません。\n",[41,242,240],{"__ignoreMap":43},[15,244,245,246,249,250,249,253,249,256,249,259,262,263,266,267,270,271,273],{},"PowerShellには数値リテラルのサフィックスとして",[41,247,248],{},"KB","/",[41,251,252],{},"MB",[41,254,255],{},"GB",[41,257,258],{},"TB",[41,260,261],{},"PB","が組み込まれている。",[41,264,265],{},"100MB","と書けば",[41,268,269],{},"104857600","になる便利機能だ。ところがフォーマット文字列の中に裸で",[41,272,252],{},"が出てくると、パーサが「ここは数値リテラルだな」と誤認識して構文エラーを吐く。",[15,275,276,277,279],{},"回避策は、",[41,278,252],{},"を文字として明示的に扱うこと。",[34,281,283],{"className":173,"code":282,"language":175,"meta":43,"style":43},"# NG: MBが数値サフィックス扱いされる\nWrite-Host \"サイズ: {0:N1} MB\" -f ($size / 1MB)\n\n# OK: フォーマット対象に埋め込むか、文字列連結にする\n$mb = [math]::Round($size / 1MB, 1)\nWrite-Host \"サイズ: $mb MB\"\n",[41,284,285,290,295,301,306,311],{"__ignoreMap":43},[118,286,287],{"class":120,"line":121},[118,288,289],{},"# NG: MBが数値サフィックス扱いされる\n",[118,291,292],{"class":120,"line":127},[118,293,294],{},"Write-Host \"サイズ: {0:N1} MB\" -f ($size / 1MB)\n",[118,296,297],{"class":120,"line":133},[118,298,300],{"emptyLinePlaceholder":299},true,"\n",[118,302,303],{"class":120,"line":195},[118,304,305],{},"# OK: フォーマット対象に埋め込むか、文字列連結にする\n",[118,307,308],{"class":120,"line":201},[118,309,310],{},"$mb = [math]::Round($size / 1MB, 1)\n",[118,312,313],{"class":120,"line":207},[118,314,315],{},"Write-Host \"サイズ: $mb MB\"\n",[15,317,318],{},"PowerShellの数値サフィックスがフォーマット文字列の中まで効いてくるとは思わなかった。ログをしばらく眺めて気づくまで、5分くらい悩んだ。",[148,320,322],{"id":321},"罠3-ffprobeがpathにない","罠3: ffprobeがPATHにない",[15,324,325],{},"分割の起点を決めるには動画のduration（再生時間）が要る。普段ならffprobeを呼べば一発だ。",[34,327,329],{"className":173,"code":328,"language":175,"meta":43,"style":43},"ffprobe -v error -show_entries format=duration -of csv=p=0 $InputFile\n",[41,330,331],{"__ignoreMap":43},[118,332,333],{"class":120,"line":121},[118,334,328],{},[15,336,337,338,341],{},"ところが実行すると",[41,339,340],{},"'ffprobe' は、内部コマンドまたは外部コマンド...として認識されていません。","と返ってきた。ffmpegのビルドによってはffprobeが同梱されていないことがある（今のWindows環境がまさにそうだった）。",[15,343,344],{},"ffprobeを別途入れるのも一手だが、ffmpegだけで完結させたい。ffmpegは入力ファイルを解析するときに標準エラー出力にdurationを書き出すので、そこから正規表現で拾えばいい。",[34,346,348],{"className":173,"code":347,"language":175,"meta":43,"style":43},"$ffmpegOutput = & ffmpeg -i $InputFile 2>&1 | Out-String\nif ($ffmpegOutput -match \"Duration:\\s(\\d+):(\\d+):(\\d+)\\.(\\d+)\") {\n    $hours = [int]$matches[1]\n    $minutes = [int]$matches[2]\n    $seconds = [int]$matches[3]\n    $totalSeconds = $hours * 3600 + $minutes * 60 + $seconds\n}\n",[41,349,350,355,360,365,370,375,380],{"__ignoreMap":43},[118,351,352],{"class":120,"line":121},[118,353,354],{},"$ffmpegOutput = & ffmpeg -i $InputFile 2>&1 | Out-String\n",[118,356,357],{"class":120,"line":127},[118,358,359],{},"if ($ffmpegOutput -match \"Duration:\\s(\\d+):(\\d+):(\\d+)\\.(\\d+)\") {\n",[118,361,362],{"class":120,"line":133},[118,363,364],{},"    $hours = [int]$matches[1]\n",[118,366,367],{"class":120,"line":195},[118,368,369],{},"    $minutes = [int]$matches[2]\n",[118,371,372],{"class":120,"line":201},[118,373,374],{},"    $seconds = [int]$matches[3]\n",[118,376,377],{"class":120,"line":207},[118,378,379],{},"    $totalSeconds = $hours * 3600 + $minutes * 60 + $seconds\n",[118,381,383],{"class":120,"line":382},7,[118,384,385],{},"}\n",[15,387,388,389,392],{},"ffmpegに",[41,390,391],{},"-i","だけ渡して実行すると、出力ファイルを指定していないのでエラー終了するが、先に入力情報は吐き出されている。そこを捕まえる。スマートではないが確実に動く。",[10,394,396],{"id":395},"最終結果-3パート残りカス01mb","最終結果: 3パート＋残りカス0.1MB",[15,398,399],{},"BOM付きで保存し直して再実行したら、分割が走った。",[34,401,404],{"className":402,"code":403,"language":39},[37],"part000: 392.4 MB\npart001: 388.1 MB\npart002: 151.2 MB\npart003: 0.1 MB\n",[41,405,403],{"__ignoreMap":43},[15,407,408],{},"狙い通り3パートすべて400MB以下に収まった。ただし4パート目に0.1MBの極小ファイルが生まれている。",[15,410,411,412,415],{},"これはffmpegのセグメント分割がキーフレーム境界にスナップする挙動のせいだ。",[41,413,414],{},"-f segment -segment_time","で3分割を指定しても、指定秒のピッタリでは切れず、直近のキーフレームで切られる。結果、3つ目のセグメント末尾からファイル末尾までの数十ミリ秒が、4つ目として独立してしまう。",[15,417,418],{},"実用上は3つで字幕生成は完結するので、part003は無視していい。気になるなら分割後に100KB以下のパートを削除する後処理を足せば綺麗になる。",[10,420,422],{"id":421},"振り返り-windows-日本語パス-ffmpegの三重苦","振り返り: Windows × 日本語パス × ffmpegの三重苦",[15,424,425],{},"今日ハマった罠を並べると、全部「Windowsで日本語パスを扱う動画スクリプト」という一点に収束していた。",[88,427,428,434,440,449],{},[91,429,430,433],{},[94,431,432],{},"Git Bashからbat直叩きの文字化け"," → batはランチャーに徹して日本語を持たせない",[91,435,436,439],{},[94,437,438],{},"BOMなしUTF-8でPowerShellがパースを投げる"," → BOM付きUTF-8で保存",[91,441,442,448],{},[94,443,444,445,447],{},"フォーマット文字列の",[41,446,252],{},"が数値サフィックス扱い"," → 変数展開で先に文字列化してから埋め込む",[91,450,451,454],{},[94,452,453],{},"ffprobeがPATHにない"," → ffmpegの標準エラー出力からdurationを正規表現で拾う",[15,456,457,458,461],{},"いずれも単体なら10分で解決する話だが、日本語パスを含むドラッグ＆ドロップ運用をまとめて実現しようとすると、4つが同時に襲いかかってくる。Windowsで動画処理スクリプトを書くときは、最初から",[94,459,460],{},"BOM付きUTF-8・batランチャー・ffmpeg単体で完結・MBは変数経由","の4点セットを前提にしておくと余計な試行錯誤が減る。",[15,463,464],{},"一度ランチャー方式を作っておけば、次に400MB制限で引っかかったときはファイルをbatにドラッグするだけで済む。たぶん来週また同じ動画サイズで困るので、そのときの自分のために作った。",[466,467,468],"style",{},"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);}",{"title":43,"searchDepth":127,"depth":127,"links":470},[471,472,473,474,480,481],{"id":12,"depth":127,"text":13},{"id":49,"depth":127,"text":50},{"id":79,"depth":127,"text":80},{"id":142,"depth":127,"text":143,"children":475},[476,477,479],{"id":150,"depth":133,"text":151},{"id":216,"depth":133,"text":478},"罠2: \"{0} MB\" のMBが数値サフィックスとして食われる",{"id":321,"depth":133,"text":322},{"id":395,"depth":127,"text":396},{"id":421,"depth":127,"text":422},"dev","Geminiの400MB制限に引っかかる大容量動画を、Git Bash非対応の日本語パスでもドラッグ＆ドロップで分割できるスクリプトを作成。BOM・ffprobe不在・数値サフィックスの罠を一つずつ潰す。","md",{},"/twitter-video-split-for-gemini","chrome-extension-x",false,"2026-04-16T00:00:00.000Z",{"title":5,"description":483},"2026-04/2026-04-16/twitter-video-split-for-gemini",[493,494,495,496,497,498],"PowerShell","ffmpeg","Windows","Gemini","動画処理","BOM",null,"N7JeiarntbGbvWU1aiYMoYLPDV2rJ4BtrKuRnsCwHHw",[],"https://log.eurekapu.com/og/blog/twitter-video-split-for-gemini.png?v=2026-04-16T00%3A00%3A00.000Z&title=Twitter%E5%8B%95%E7%94%BB%E3%81%AEGemini%E7%94%A8400MB%E5%88%86%E5%89%B2%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%20-%20bat%EF%BC%8BPowerShell%E3%83%A9%E3%83%B3%E3%83%81%E3%83%A3%E3%83%BC%E6%96%B9%E5%BC%8F&author=Kei%20Komatsu&sig=595b776ae016c066",1780786052290]