[{"data":1,"prerenderedAt":11139},["ShallowReactive",2],{"blog-/ja/blog/seedance-2-api-tutorial-python":3},{"id":4,"title":5,"body":6,"description":11128,"extension":11129,"meta":11130,"navigation":57,"path":11135,"seo":11136,"stem":11137,"__hash__":11138},"content/ja/blog/seedance-2-api-tutorial-python.md","Seedance 2.0 API チュートリアル：Python でゼロから初めての AI 動画を生成",{"type":7,"value":8,"toc":11070},"minimark",[9,13,16,31,43,46,51,54,65,68,90,94,123,126,199,201,205,214,217,245,248,269,288,297,305,307,311,314,328,334,468,471,507,510,1026,1029,1065,1239,1249,1252,1261,1263,1267,1270,1736,1739,1828,1831,1843,1847,1854,2032,2035,2157,2171,2175,2180,2188,2191,2199,2206,2213,2215,2219,2226,2262,2265,2268,2274,2344,2348,2354,2360,2421,2433,2436,2439,2565,2579,2586,2597,2599,2603,2615,2621,2884,2887,2938,2942,2968,2971,3053,3056,3208,3214,3217,3271,3281,3289,3293,3296,3375,3382,3384,3387,3390,3609,3638,3641,3646,3650,3741,3749,3754,3849,3856,3861,3949,3954,4029,4046,4049,4052,4123,4136,4155,4157,4160,4163,4166,4169,4227,4249,4252,4257,4300,4306,4311,4365,4370,4375,4427,4436,4441,4484,4491,4496,4550,4556,4561,4604,4607,4612,4666,4672,4675,4886,4889,4892,4896,5643,5646,5678,5685,5689,5692,6272,6283,6285,6289,6296,6299,6305,6310,6468,6474,6478,6540,6544,6547,7739,7742,7765,7768,7795,7799,7808,7856,7859,7865,7871,7918,7933,7937,7940,8112,8116,8195,8202,8204,8208,8211,8216,8764,8767,8789,8791,8794,8797,8800,8839,8842,8864,8867,8870,8904,8914,8916,8919,8923,8929,8933,8939,8943,8949,8953,8964,8968,8981,8985,8995,8999,9014,9018,9025,9029,9045,9049,9056,9058,9061,9064,11044,11058,11066],[10,11,12],"p",{},"Seedance 2.0 は ByteDance の最先端 AI 動画生成モデルです — マルチモーダル参照、ネイティブオーディオ生成、シネマティックなカメラ制御、最大 1080p で 4〜15 秒の動画生成に対応しています。このチュートリアルでは、API Key の取得から最初の動画ダウンロードまで、Python で API ワークフロー全体を解説します。",[10,14,15],{},"このチュートリアルを終えると、テキストから動画、画像から動画、非同期 polling、webhook 処理、エラーリカバリーの完全な実行可能コードが手に入ります。すべてのコード例は実際の API でテスト済みです。",[17,18,19],"blockquote",{},[10,20,21,25,26,30],{},[22,23,24],"strong",{},"Seedance 2.0 と 1.5 について："," Seedance 2.0 は段階的にリリース中です。今すぐ ",[27,28,29],"code",{},"seedance-1.5-pro"," で完全なワークフローをテストできます — 2.0 が完全に利用可能になったら、モデル名を変更するだけです。すべてのエンドポイント、パラメータ、レスポンス形式は同一です。2.0 の主な違い：マルチモーダル参照（画像・動画・音声の混合入力）、ネイティブオーディオ生成、物理シミュレーションの改善、動画編集機能。このチュートリアルの内容はどちらのバージョンでも動作します。",[10,32,33],{},[22,34,35,42],{},[36,37,41],"a",{"href":38,"rel":39},"https://evolink.ai/early-access",[40],"nofollow","無料 API Key を取得","して、一緒に手を動かしましょう。",[44,45],"hr",{},[47,48,50],"h2",{"id":49},"何を作るかそして何が必要か","何を作るか（そして何が必要か）",[10,52,53],{},"まず Seedance で生成した動画を見てみましょう — たった 1 回の API コールで作成されました：",[55,56,59,60],"video",{"autoPlay":57,"loop":57,"muted":57,"playsInline":57,"style":58},true,"width:100%;border-radius:12px;margin:1.5em 0","\n  ",[61,62],"source",{"src":63,"type":64},"https://cdn.evolink.ai/seedance2api/%E5%B0%8F%E5%A5%B3%E5%AD%A9%E5%9B%BE%E4%B9%A6%E9%A6%86%E5%A5%87%E9%81%87.mp4","video/mp4",[10,66,67],{},"このチュートリアルで書く Python コード：",[69,70,71,75,78,81,84,87],"ol",{},[72,73,74],"li",{},"テキストプロンプトを送信 → 生成された動画を取得",[72,76,77],{},"画像を送信 → アニメーション動画に変換",[72,79,80],{},"非同期で結果を polling",[72,82,83],{},"プロダクションコードのようにエラーとリトライを処理",[72,85,86],{},"webhook で結果を受信（polling 不要）",[72,88,89],{},"進行中のタスクを必要に応じてキャンセル",[91,92,93],"h3",{"id":93},"前提条件",[95,96,97,107,117],"ul",{},[72,98,99,102,103,106],{},[22,100,101],{},"Python 3.8+","（",[27,104,105],{},"python3 --version"," で確認）",[72,108,109,112,113,116],{},[22,110,111],{},"requests"," ライブラリ（",[27,114,115],{},"pip install requests","）",[72,118,119,122],{},[22,120,121],{},"EvoLink API Key","（無料登録 — 次のセクションで取得方法を説明します）",[10,124,125],{},"GPU も Docker も複雑なセットアップも不要です。Python と API Key だけで OK。",[17,127,128,134],{},[10,129,130,133],{},[22,131,132],{},"ヒント："," プロダクションアプリを開発中なら、仮想環境で依存関係を分離することをお勧めします：",[135,136,141],"pre",{"className":137,"code":138,"language":139,"meta":140,"style":140},"language-bash shiki shiki-themes github-dark","python3 -m venv seedance-env\nsource seedance-env/bin/activate  # macOS/Linux\nseedance-env\\Scripts\\activate     # Windows\npip install requests flask\n","bash","",[27,142,143,163,175,184],{"__ignoreMap":140},[144,145,148,152,156,160],"span",{"class":146,"line":147},"line",1,[144,149,151],{"class":150},"svObZ","python3",[144,153,155],{"class":154},"sDLfK"," -m",[144,157,159],{"class":158},"sU2Wk"," venv",[144,161,162],{"class":158}," seedance-env\n",[144,164,166,168,171],{"class":146,"line":165},2,[144,167,61],{"class":154},[144,169,170],{"class":158}," seedance-env/bin/activate",[144,172,174],{"class":173},"sAwPA","  # macOS/Linux\n",[144,176,178,181],{"class":146,"line":177},3,[144,179,180],{"class":150},"seedance-env\\Scripts\\activate",[144,182,183],{"class":173},"     # Windows\n",[144,185,187,190,193,196],{"class":146,"line":186},4,[144,188,189],{"class":150},"pip",[144,191,192],{"class":158}," install",[144,194,195],{"class":158}," requests",[144,197,198],{"class":158}," flask\n",[44,200],{},[47,202,204],{"id":203},"api-key-を取得する","API Key を取得する",[10,206,207,208,213],{},"Seedance 2.0 は ",[36,209,212],{"href":210,"rel":211},"https://evolink.ai",[40],"EvoLink"," を通じて提供されています。EvoLink は 1 つの API Key で Seedance 2.0、Kling など複数の AI 動画モデルに統合アクセスできる API ゲートウェイです。",[10,215,216],{},"取得手順：",[69,218,219,226,232,238],{},[72,220,221,225],{},[36,222,224],{"href":38,"rel":223},[40],"evolink.ai/early-access"," でアカウントを作成",[72,227,228,231],{},[22,229,230],{},"Dashboard → API Keys"," に移動",[72,233,234,237],{},[22,235,236],{},"Create New Key"," をクリック",[72,239,240,241,244],{},"Key をコピー — ",[27,242,243],{},"sk-"," で始まります",[10,246,247],{},"Key は安全に保管してください。バージョン管理にコミットしないでください。環境変数を使います：",[135,249,251],{"className":137,"code":250,"language":139,"meta":140,"style":140},"export EVOLINK_API_KEY=\"sk-your-api-key-here\"\n",[27,252,253],{"__ignoreMap":140},[144,254,255,259,263,266],{"class":146,"line":147},[144,256,258],{"class":257},"snl16","export",[144,260,262],{"class":261},"s95oV"," EVOLINK_API_KEY",[144,264,265],{"class":257},"=",[144,267,268],{"class":158},"\"sk-your-api-key-here\"\n",[10,270,271,272,275,276,279,280,283,284,287],{},"このコマンドは現在のターミナルセッションで ",[27,273,274],{},"EVOLINK_API_KEY"," 環境変数を設定します。macOS/Linux では ",[27,277,278],{},"~/.bashrc"," や ",[27,281,282],{},"~/.zshrc"," に追加して永続化できます。Windows ではコマンドプロンプトで ",[27,285,286],{},"set EVOLINK_API_KEY=sk-your-api-key-here"," を使うか、システムのプロパティ → 環境変数で設定してください。",[10,289,290,291,296],{},"アカウントにはお試し用の初期クレジットが含まれています。現在の料金詳細は",[36,292,295],{"href":293,"rel":294},"https://seedance2api.app/docs/getting-started",[40],"スタートガイド","をご確認ください。",[17,298,299],{},[10,300,301,304],{},[22,302,303],{},"よくある間違い："," API Key をソースファイルにハードコードしないでください。GitHub にプッシュすると、自動化されたクローラーが数分以内に見つけます。必ず環境変数や AWS Secrets Manager、HashiCorp Vault などのシークレット管理サービスを使用してください。",[44,306],{},[47,308,310],{"id":309},"python-環境のセットアップ","Python 環境のセットアップ",[10,312,313],{},"必要なライブラリをインストールします：",[135,315,317],{"className":137,"code":316,"language":139,"meta":140,"style":140},"pip install requests\n",[27,318,319],{"__ignoreMap":140},[144,320,321,323,325],{"class":146,"line":147},[144,322,189],{"class":150},[144,324,192],{"class":158},[144,326,327],{"class":158}," requests\n",[10,329,330,333],{},[27,331,332],{},"seedance_tutorial.py"," というファイルを作成し、以下の基本コードを追加してください。このチュートリアルのすべての例はこのコードをベースにしています：",[135,335,339],{"className":336,"code":337,"language":338,"meta":140,"style":140},"language-python shiki shiki-themes github-dark","import requests\nimport time\nimport os\nimport json\n\n# ── 設定 ─────────────────────────────────────────────────────\nAPI_KEY = os.getenv(\"EVOLINK_API_KEY\", \"sk-your-api-key-here\")\nBASE_URL = \"https://api.evolink.ai/v1\"\nHEADERS = {\n    \"Authorization\": f\"Bearer {API_KEY}\",\n    \"Content-Type\": \"application/json\"\n}\n","python",[27,340,341,348,355,362,369,375,381,405,416,427,451,462],{"__ignoreMap":140},[144,342,343,346],{"class":146,"line":147},[144,344,345],{"class":257},"import",[144,347,327],{"class":261},[144,349,350,352],{"class":146,"line":165},[144,351,345],{"class":257},[144,353,354],{"class":261}," time\n",[144,356,357,359],{"class":146,"line":177},[144,358,345],{"class":257},[144,360,361],{"class":261}," os\n",[144,363,364,366],{"class":146,"line":186},[144,365,345],{"class":257},[144,367,368],{"class":261}," json\n",[144,370,372],{"class":146,"line":371},5,[144,373,374],{"emptyLinePlaceholder":57},"\n",[144,376,378],{"class":146,"line":377},6,[144,379,380],{"class":173},"# ── 設定 ─────────────────────────────────────────────────────\n",[144,382,384,387,390,393,396,399,402],{"class":146,"line":383},7,[144,385,386],{"class":154},"API_KEY",[144,388,389],{"class":257}," =",[144,391,392],{"class":261}," os.getenv(",[144,394,395],{"class":158},"\"EVOLINK_API_KEY\"",[144,397,398],{"class":261},", ",[144,400,401],{"class":158},"\"sk-your-api-key-here\"",[144,403,404],{"class":261},")\n",[144,406,408,411,413],{"class":146,"line":407},8,[144,409,410],{"class":154},"BASE_URL",[144,412,389],{"class":257},[144,414,415],{"class":158}," \"https://api.evolink.ai/v1\"\n",[144,417,419,422,424],{"class":146,"line":418},9,[144,420,421],{"class":154},"HEADERS",[144,423,389],{"class":257},[144,425,426],{"class":261}," {\n",[144,428,430,433,436,439,442,445,448],{"class":146,"line":429},10,[144,431,432],{"class":158},"    \"Authorization\"",[144,434,435],{"class":261},": ",[144,437,438],{"class":257},"f",[144,440,441],{"class":158},"\"Bearer ",[144,443,444],{"class":154},"{API_KEY}",[144,446,447],{"class":158},"\"",[144,449,450],{"class":261},",\n",[144,452,454,457,459],{"class":146,"line":453},11,[144,455,456],{"class":158},"    \"Content-Type\"",[144,458,435],{"class":261},[144,460,461],{"class":158},"\"application/json\"\n",[144,463,465],{"class":146,"line":464},12,[144,466,467],{"class":261},"}\n",[10,469,470],{},"1 行ずつ解説します：",[95,472,473,481,492],{},[72,474,475,480],{},[22,476,477],{},[27,478,479],{},"os.getenv(\"EVOLINK_API_KEY\", \"sk-your-api-key-here\")"," — 環境変数から API Key を読み取ります。第 2 引数はデフォルト値です（ローカルテスト時のみ実際の Key に置き換えてください）。",[72,482,483,487,488,491],{},[22,484,485],{},[27,486,410],{}," — すべての EvoLink API エンドポイントのルート URL です。すべてのリクエストは ",[27,489,490],{},"https://api.evolink.ai/v1/..."," に送信されます。",[72,493,494,498,499,502,503,506],{},[22,495,496],{},[27,497,421],{}," — すべてのリクエストに含まれる 2 つのヘッダー：",[27,500,501],{},"Authorization"," は Bearer Token 方式で API Key を送信し、",[27,504,505],{},"Content-Type"," はサーバーに JSON を送信していることを伝えます。",[10,508,509],{},"次に再利用可能なヘルパー関数を追加します：",[135,511,513],{"className":336,"code":512,"language":338,"meta":140,"style":140},"# ── 再利用可能な Polling ヘルパー ──────────────────────────────\ndef wait_for_video(task_id, poll_interval=10, timeout=600):\n    \"\"\"\n    動画生成タスクを完了または失敗するまで polling します。\n    \n    Args:\n        task_id: 生成エンドポイントが返したタスク ID。\n        poll_interval: polling 間隔（秒、デフォルト 10）。\n        timeout: 最大待機時間（秒、デフォルト 600）。\n    \n    Returns:\n        dict: 動画 URL を含む完了したタスクレスポンス。\n    \n    Raises:\n        TimeoutError: タスクがタイムアウト内に完了しなかった場合。\n        RuntimeError: タスクが失敗した場合。\n    \"\"\"\n    elapsed = 0\n    while elapsed \u003C timeout:\n        # GET リクエストでタスクの現在のステータスを確認\n        response = requests.get(\n            f\"{BASE_URL}/tasks/{task_id}\",\n            headers=HEADERS\n        )\n        # HTTP ステータスコードがエラーを示す場合、例外を発生\n        response.raise_for_status()\n        task = response.json()\n\n        # レスポンスからステータスと進捗を抽出\n        status = task[\"status\"]\n        progress = task.get(\"progress\", 0)\n        print(f\"  [{elapsed}s] Status: {status} | Progress: {progress}%\")\n\n        # 終了状態を確認\n        if status == \"completed\":\n            return task\n        elif status == \"failed\":\n            error_info = task.get(\"error\", {})\n            raise RuntimeError(\n                f\"Task {task_id} failed: {error_info.get('message', 'Unknown error')}\"\n            )\n\n        # 次の polling まで待機\n        time.sleep(poll_interval)\n        elapsed += poll_interval\n\n    raise TimeoutError(f\"Task {task_id} timed out after {timeout}s\")\n",[27,514,515,520,547,552,557,562,567,572,577,582,586,591,596,601,607,613,619,624,635,650,656,667,694,706,712,718,724,735,740,746,763,784,830,835,841,859,868,883,899,911,950,956,961,967,973,985,990],{"__ignoreMap":140},[144,516,517],{"class":146,"line":147},[144,518,519],{"class":173},"# ── 再利用可能な Polling ヘルパー ──────────────────────────────\n",[144,521,522,525,528,531,533,536,539,541,544],{"class":146,"line":165},[144,523,524],{"class":257},"def",[144,526,527],{"class":150}," wait_for_video",[144,529,530],{"class":261},"(task_id, poll_interval",[144,532,265],{"class":257},[144,534,535],{"class":154},"10",[144,537,538],{"class":261},", timeout",[144,540,265],{"class":257},[144,542,543],{"class":154},"600",[144,545,546],{"class":261},"):\n",[144,548,549],{"class":146,"line":177},[144,550,551],{"class":158},"    \"\"\"\n",[144,553,554],{"class":146,"line":186},[144,555,556],{"class":158},"    動画生成タスクを完了または失敗するまで polling します。\n",[144,558,559],{"class":146,"line":371},[144,560,561],{"class":158},"    \n",[144,563,564],{"class":146,"line":377},[144,565,566],{"class":158},"    Args:\n",[144,568,569],{"class":146,"line":383},[144,570,571],{"class":158},"        task_id: 生成エンドポイントが返したタスク ID。\n",[144,573,574],{"class":146,"line":407},[144,575,576],{"class":158},"        poll_interval: polling 間隔（秒、デフォルト 10）。\n",[144,578,579],{"class":146,"line":418},[144,580,581],{"class":158},"        timeout: 最大待機時間（秒、デフォルト 600）。\n",[144,583,584],{"class":146,"line":429},[144,585,561],{"class":158},[144,587,588],{"class":146,"line":453},[144,589,590],{"class":158},"    Returns:\n",[144,592,593],{"class":146,"line":464},[144,594,595],{"class":158},"        dict: 動画 URL を含む完了したタスクレスポンス。\n",[144,597,599],{"class":146,"line":598},13,[144,600,561],{"class":158},[144,602,604],{"class":146,"line":603},14,[144,605,606],{"class":158},"    Raises:\n",[144,608,610],{"class":146,"line":609},15,[144,611,612],{"class":158},"        TimeoutError: タスクがタイムアウト内に完了しなかった場合。\n",[144,614,616],{"class":146,"line":615},16,[144,617,618],{"class":158},"        RuntimeError: タスクが失敗した場合。\n",[144,620,622],{"class":146,"line":621},17,[144,623,551],{"class":158},[144,625,627,630,632],{"class":146,"line":626},18,[144,628,629],{"class":261},"    elapsed ",[144,631,265],{"class":257},[144,633,634],{"class":154}," 0\n",[144,636,638,641,644,647],{"class":146,"line":637},19,[144,639,640],{"class":257},"    while",[144,642,643],{"class":261}," elapsed ",[144,645,646],{"class":257},"\u003C",[144,648,649],{"class":261}," timeout:\n",[144,651,653],{"class":146,"line":652},20,[144,654,655],{"class":173},"        # GET リクエストでタスクの現在のステータスを確認\n",[144,657,659,662,664],{"class":146,"line":658},21,[144,660,661],{"class":261},"        response ",[144,663,265],{"class":257},[144,665,666],{"class":261}," requests.get(\n",[144,668,670,673,675,678,681,684,687,690,692],{"class":146,"line":669},22,[144,671,672],{"class":257},"            f",[144,674,447],{"class":158},[144,676,677],{"class":154},"{BASE_URL}",[144,679,680],{"class":158},"/tasks/",[144,682,683],{"class":154},"{",[144,685,686],{"class":261},"task_id",[144,688,689],{"class":154},"}",[144,691,447],{"class":158},[144,693,450],{"class":261},[144,695,697,701,703],{"class":146,"line":696},23,[144,698,700],{"class":699},"s9osk","            headers",[144,702,265],{"class":257},[144,704,705],{"class":154},"HEADERS\n",[144,707,709],{"class":146,"line":708},24,[144,710,711],{"class":261},"        )\n",[144,713,715],{"class":146,"line":714},25,[144,716,717],{"class":173},"        # HTTP ステータスコードがエラーを示す場合、例外を発生\n",[144,719,721],{"class":146,"line":720},26,[144,722,723],{"class":261},"        response.raise_for_status()\n",[144,725,727,730,732],{"class":146,"line":726},27,[144,728,729],{"class":261},"        task ",[144,731,265],{"class":257},[144,733,734],{"class":261}," response.json()\n",[144,736,738],{"class":146,"line":737},28,[144,739,374],{"emptyLinePlaceholder":57},[144,741,743],{"class":146,"line":742},29,[144,744,745],{"class":173},"        # レスポンスからステータスと進捗を抽出\n",[144,747,749,752,754,757,760],{"class":146,"line":748},30,[144,750,751],{"class":261},"        status ",[144,753,265],{"class":257},[144,755,756],{"class":261}," task[",[144,758,759],{"class":158},"\"status\"",[144,761,762],{"class":261},"]\n",[144,764,766,769,771,774,777,779,782],{"class":146,"line":765},31,[144,767,768],{"class":261},"        progress ",[144,770,265],{"class":257},[144,772,773],{"class":261}," task.get(",[144,775,776],{"class":158},"\"progress\"",[144,778,398],{"class":261},[144,780,781],{"class":154},"0",[144,783,404],{"class":261},[144,785,787,790,793,795,798,800,803,805,808,810,813,815,818,820,823,825,828],{"class":146,"line":786},32,[144,788,789],{"class":154},"        print",[144,791,792],{"class":261},"(",[144,794,438],{"class":257},[144,796,797],{"class":158},"\"  [",[144,799,683],{"class":154},[144,801,802],{"class":261},"elapsed",[144,804,689],{"class":154},[144,806,807],{"class":158},"s] Status: ",[144,809,683],{"class":154},[144,811,812],{"class":261},"status",[144,814,689],{"class":154},[144,816,817],{"class":158}," | Progress: ",[144,819,683],{"class":154},[144,821,822],{"class":261},"progress",[144,824,689],{"class":154},[144,826,827],{"class":158},"%\"",[144,829,404],{"class":261},[144,831,833],{"class":146,"line":832},33,[144,834,374],{"emptyLinePlaceholder":57},[144,836,838],{"class":146,"line":837},34,[144,839,840],{"class":173},"        # 終了状態を確認\n",[144,842,844,847,850,853,856],{"class":146,"line":843},35,[144,845,846],{"class":257},"        if",[144,848,849],{"class":261}," status ",[144,851,852],{"class":257},"==",[144,854,855],{"class":158}," \"completed\"",[144,857,858],{"class":261},":\n",[144,860,862,865],{"class":146,"line":861},36,[144,863,864],{"class":257},"            return",[144,866,867],{"class":261}," task\n",[144,869,871,874,876,878,881],{"class":146,"line":870},37,[144,872,873],{"class":257},"        elif",[144,875,849],{"class":261},[144,877,852],{"class":257},[144,879,880],{"class":158}," \"failed\"",[144,882,858],{"class":261},[144,884,886,889,891,893,896],{"class":146,"line":885},38,[144,887,888],{"class":261},"            error_info ",[144,890,265],{"class":257},[144,892,773],{"class":261},[144,894,895],{"class":158},"\"error\"",[144,897,898],{"class":261},", {})\n",[144,900,902,905,908],{"class":146,"line":901},39,[144,903,904],{"class":257},"            raise",[144,906,907],{"class":154}," RuntimeError",[144,909,910],{"class":261},"(\n",[144,912,914,917,920,922,924,926,929,931,934,937,939,942,945,947],{"class":146,"line":913},40,[144,915,916],{"class":257},"                f",[144,918,919],{"class":158},"\"Task ",[144,921,683],{"class":154},[144,923,686],{"class":261},[144,925,689],{"class":154},[144,927,928],{"class":158}," failed: ",[144,930,683],{"class":154},[144,932,933],{"class":261},"error_info.get(",[144,935,936],{"class":158},"'message'",[144,938,398],{"class":261},[144,940,941],{"class":158},"'Unknown error'",[144,943,944],{"class":261},")",[144,946,689],{"class":154},[144,948,949],{"class":158},"\"\n",[144,951,953],{"class":146,"line":952},41,[144,954,955],{"class":261},"            )\n",[144,957,959],{"class":146,"line":958},42,[144,960,374],{"emptyLinePlaceholder":57},[144,962,964],{"class":146,"line":963},43,[144,965,966],{"class":173},"        # 次の polling まで待機\n",[144,968,970],{"class":146,"line":969},44,[144,971,972],{"class":261},"        time.sleep(poll_interval)\n",[144,974,976,979,982],{"class":146,"line":975},45,[144,977,978],{"class":261},"        elapsed ",[144,980,981],{"class":257},"+=",[144,983,984],{"class":261}," poll_interval\n",[144,986,988],{"class":146,"line":987},46,[144,989,374],{"emptyLinePlaceholder":57},[144,991,993,996,999,1001,1003,1005,1007,1009,1011,1014,1016,1019,1021,1024],{"class":146,"line":992},47,[144,994,995],{"class":257},"    raise",[144,997,998],{"class":154}," TimeoutError",[144,1000,792],{"class":261},[144,1002,438],{"class":257},[144,1004,919],{"class":158},[144,1006,683],{"class":154},[144,1008,686],{"class":261},[144,1010,689],{"class":154},[144,1012,1013],{"class":158}," timed out after ",[144,1015,683],{"class":154},[144,1017,1018],{"class":261},"timeout",[144,1020,689],{"class":154},[144,1022,1023],{"class":158},"s\"",[144,1025,404],{"class":261},[10,1027,1028],{},"この関数の主な設計判断：",[95,1030,1031,1039,1047,1055],{},[72,1032,1033,1038],{},[22,1034,1035],{},[27,1036,1037],{},"poll_interval=10"," — 10 秒が最適です。速すぎると API クォータを浪費し、遅すぎるとワークフローが遅延します。",[72,1040,1041,1046],{},[22,1042,1043],{},[27,1044,1045],{},"timeout=600"," — 10 分は十分な余裕があります。ほとんどの動画は 30〜120 秒で完了しますが、キュー混雑などのエッジケースをカバーします。",[72,1048,1049,1054],{},[22,1050,1051],{},[27,1052,1053],{},"response.raise_for_status()"," — HTTP エラー（4xx/5xx）を Python 例外に変換し、サイレントに通過するのを防ぎます。",[72,1056,1057,1060,1061,1064],{},[22,1058,1059],{},"進捗表示"," — ",[27,1062,1063],{},"[elapsed]s"," プレフィックスでタイミングを把握できます。遅い生成のデバッグに便利です。",[135,1066,1068],{"className":336,"code":1067,"language":338,"meta":140,"style":140},"# ── ヘルパー：動画ダウンロード ─────────────────────────────────\ndef download_video(url, filename=\"output.mp4\"):\n    \"\"\"URL から動画ファイルをダウンロードします。\"\"\"\n    print(f\"Downloading video to {filename}...\")\n    resp = requests.get(url, stream=True)\n    resp.raise_for_status()\n    with open(filename, \"wb\") as f:\n        for chunk in resp.iter_content(chunk_size=8192):\n            f.write(chunk)\n    print(f\"Saved: {filename} ({os.path.getsize(filename) / 1024:.0f} KB)\")\n",[27,1069,1070,1075,1092,1097,1121,1141,1146,1169,1193,1198],{"__ignoreMap":140},[144,1071,1072],{"class":146,"line":147},[144,1073,1074],{"class":173},"# ── ヘルパー：動画ダウンロード ─────────────────────────────────\n",[144,1076,1077,1079,1082,1085,1087,1090],{"class":146,"line":165},[144,1078,524],{"class":257},[144,1080,1081],{"class":150}," download_video",[144,1083,1084],{"class":261},"(url, filename",[144,1086,265],{"class":257},[144,1088,1089],{"class":158},"\"output.mp4\"",[144,1091,546],{"class":261},[144,1093,1094],{"class":146,"line":177},[144,1095,1096],{"class":158},"    \"\"\"URL から動画ファイルをダウンロードします。\"\"\"\n",[144,1098,1099,1102,1104,1106,1109,1111,1114,1116,1119],{"class":146,"line":186},[144,1100,1101],{"class":154},"    print",[144,1103,792],{"class":261},[144,1105,438],{"class":257},[144,1107,1108],{"class":158},"\"Downloading video to ",[144,1110,683],{"class":154},[144,1112,1113],{"class":261},"filename",[144,1115,689],{"class":154},[144,1117,1118],{"class":158},"...\"",[144,1120,404],{"class":261},[144,1122,1123,1126,1128,1131,1134,1136,1139],{"class":146,"line":371},[144,1124,1125],{"class":261},"    resp ",[144,1127,265],{"class":257},[144,1129,1130],{"class":261}," requests.get(url, ",[144,1132,1133],{"class":699},"stream",[144,1135,265],{"class":257},[144,1137,1138],{"class":154},"True",[144,1140,404],{"class":261},[144,1142,1143],{"class":146,"line":377},[144,1144,1145],{"class":261},"    resp.raise_for_status()\n",[144,1147,1148,1151,1154,1157,1160,1163,1166],{"class":146,"line":383},[144,1149,1150],{"class":257},"    with",[144,1152,1153],{"class":154}," open",[144,1155,1156],{"class":261},"(filename, ",[144,1158,1159],{"class":158},"\"wb\"",[144,1161,1162],{"class":261},") ",[144,1164,1165],{"class":257},"as",[144,1167,1168],{"class":261}," f:\n",[144,1170,1171,1174,1177,1180,1183,1186,1188,1191],{"class":146,"line":407},[144,1172,1173],{"class":257},"        for",[144,1175,1176],{"class":261}," chunk ",[144,1178,1179],{"class":257},"in",[144,1181,1182],{"class":261}," resp.iter_content(",[144,1184,1185],{"class":699},"chunk_size",[144,1187,265],{"class":257},[144,1189,1190],{"class":154},"8192",[144,1192,546],{"class":261},[144,1194,1195],{"class":146,"line":418},[144,1196,1197],{"class":261},"            f.write(chunk)\n",[144,1199,1200,1202,1204,1206,1209,1211,1213,1215,1218,1220,1223,1226,1229,1232,1234,1237],{"class":146,"line":429},[144,1201,1101],{"class":154},[144,1203,792],{"class":261},[144,1205,438],{"class":257},[144,1207,1208],{"class":158},"\"Saved: ",[144,1210,683],{"class":154},[144,1212,1113],{"class":261},[144,1214,689],{"class":154},[144,1216,1217],{"class":158}," (",[144,1219,683],{"class":154},[144,1221,1222],{"class":261},"os.path.getsize(filename) ",[144,1224,1225],{"class":257},"/",[144,1227,1228],{"class":154}," 1024",[144,1230,1231],{"class":257},":.0f",[144,1233,689],{"class":154},[144,1235,1236],{"class":158}," KB)\"",[144,1238,404],{"class":261},[10,1240,1241,1242,1245,1246,1248],{},"この関数は 8 KB 単位でストリーミングダウンロードし、動画全体をメモリに読み込みません。これは重要です — 生成された動画は 10〜50 MB になることがあります。",[27,1243,1244],{},"stream=True"," パラメータは ",[27,1247,111],{}," に段階的にダウンロードするよう指示します。",[10,1250,1251],{},"以上の 3 つ — 設定、polling、ダウンロード — が基盤です。以降のすべてのコード例でこれらを使用します。繰り返しません — 新しい payload だけを示します。",[10,1253,1254,1255,1260],{},"完全な API リファレンスは",[36,1256,1259],{"href":1257,"rel":1258},"https://seedance2api.app/docs/video-generation",[40],"動画生成ドキュメント","をご覧ください。",[44,1262],{},[47,1264,1266],{"id":1265},"最初の動画を生成するテキストから動画","最初の動画を生成する（テキストから動画）",[10,1268,1269],{},"動画を生成しましょう。スクリプトに以下のコードを追加してください：",[135,1271,1273],{"className":336,"code":1272,"language":338,"meta":140,"style":140},"# ── テキストから動画 ──────────────────────────────────────────\ndef text_to_video():\n    payload = {\n        \"model\": \"seedance-2.0\",          # 使用する AI モデル\n        \"prompt\": (\n            \"A golden retriever puppy chases a butterfly through \"\n            \"a sunlit meadow. The camera follows the puppy with a \"\n            \"smooth tracking shot as wildflowers sway in the breeze.\"\n        ),\n        \"duration\": 5,                     # 動画の長さ：4-15 秒\n        \"quality\": \"720p\",                 # 解像度：480p、720p、1080p\n        \"aspect_ratio\": \"16:9\",            # 標準ワイドスクリーン\n        \"generate_audio\": True             # AI がマッチするオーディオを生成\n    }\n\n    print(\"Submitting text-to-video request...\")\n    response = requests.post(\n        f\"{BASE_URL}/videos/generations\",  # 動画生成エンドポイント\n        headers=HEADERS,                   # 認証 + content-type ヘッダー\n        json=payload                       # 自動的に JSON にシリアライズ\n    )\n    response.raise_for_status()            # 200 以外なら例外を発生\n    task = response.json()                 # JSON レスポンスをパース\n\n    # レスポンスの主要情報を出力\n    print(f\"Task created: {task['id']}\")\n    print(f\"Estimated time: {task['task_info']['estimated_time']}s\")\n    print(f\"Credits reserved: {task['usage']['credits_reserved']}\")\n\n    # 動画が準備できるまで polling\n    result = wait_for_video(task[\"id\"])\n\n    # results 配列に 1 つ以上の動画 URL が含まれる\n    video_url = result[\"results\"][0]\n    print(f\"\\nVideo URL: {video_url}\")\n    download_video(video_url, \"my_first_video.mp4\")\n\n    return result\n\n\nif __name__ == \"__main__\":\n    text_to_video()\n",[27,1274,1275,1280,1290,1299,1315,1323,1328,1333,1338,1343,1359,1375,1391,1403,1408,1412,1423,1433,1451,1466,1479,1484,1492,1505,1509,1514,1542,1574,1605,1609,1614,1630,1634,1639,1658,1685,1695,1699,1707,1711,1715,1731],{"__ignoreMap":140},[144,1276,1277],{"class":146,"line":147},[144,1278,1279],{"class":173},"# ── テキストから動画 ──────────────────────────────────────────\n",[144,1281,1282,1284,1287],{"class":146,"line":165},[144,1283,524],{"class":257},[144,1285,1286],{"class":150}," text_to_video",[144,1288,1289],{"class":261},"():\n",[144,1291,1292,1295,1297],{"class":146,"line":177},[144,1293,1294],{"class":261},"    payload ",[144,1296,265],{"class":257},[144,1298,426],{"class":261},[144,1300,1301,1304,1306,1309,1312],{"class":146,"line":186},[144,1302,1303],{"class":158},"        \"model\"",[144,1305,435],{"class":261},[144,1307,1308],{"class":158},"\"seedance-2.0\"",[144,1310,1311],{"class":261},",          ",[144,1313,1314],{"class":173},"# 使用する AI モデル\n",[144,1316,1317,1320],{"class":146,"line":371},[144,1318,1319],{"class":158},"        \"prompt\"",[144,1321,1322],{"class":261},": (\n",[144,1324,1325],{"class":146,"line":377},[144,1326,1327],{"class":158},"            \"A golden retriever puppy chases a butterfly through \"\n",[144,1329,1330],{"class":146,"line":383},[144,1331,1332],{"class":158},"            \"a sunlit meadow. The camera follows the puppy with a \"\n",[144,1334,1335],{"class":146,"line":407},[144,1336,1337],{"class":158},"            \"smooth tracking shot as wildflowers sway in the breeze.\"\n",[144,1339,1340],{"class":146,"line":418},[144,1341,1342],{"class":261},"        ),\n",[144,1344,1345,1348,1350,1353,1356],{"class":146,"line":429},[144,1346,1347],{"class":158},"        \"duration\"",[144,1349,435],{"class":261},[144,1351,1352],{"class":154},"5",[144,1354,1355],{"class":261},",                     ",[144,1357,1358],{"class":173},"# 動画の長さ：4-15 秒\n",[144,1360,1361,1364,1366,1369,1372],{"class":146,"line":453},[144,1362,1363],{"class":158},"        \"quality\"",[144,1365,435],{"class":261},[144,1367,1368],{"class":158},"\"720p\"",[144,1370,1371],{"class":261},",                 ",[144,1373,1374],{"class":173},"# 解像度：480p、720p、1080p\n",[144,1376,1377,1380,1382,1385,1388],{"class":146,"line":464},[144,1378,1379],{"class":158},"        \"aspect_ratio\"",[144,1381,435],{"class":261},[144,1383,1384],{"class":158},"\"16:9\"",[144,1386,1387],{"class":261},",            ",[144,1389,1390],{"class":173},"# 標準ワイドスクリーン\n",[144,1392,1393,1396,1398,1400],{"class":146,"line":598},[144,1394,1395],{"class":158},"        \"generate_audio\"",[144,1397,435],{"class":261},[144,1399,1138],{"class":154},[144,1401,1402],{"class":173},"             # AI がマッチするオーディオを生成\n",[144,1404,1405],{"class":146,"line":603},[144,1406,1407],{"class":261},"    }\n",[144,1409,1410],{"class":146,"line":609},[144,1411,374],{"emptyLinePlaceholder":57},[144,1413,1414,1416,1418,1421],{"class":146,"line":615},[144,1415,1101],{"class":154},[144,1417,792],{"class":261},[144,1419,1420],{"class":158},"\"Submitting text-to-video request...\"",[144,1422,404],{"class":261},[144,1424,1425,1428,1430],{"class":146,"line":621},[144,1426,1427],{"class":261},"    response ",[144,1429,265],{"class":257},[144,1431,1432],{"class":261}," requests.post(\n",[144,1434,1435,1438,1440,1442,1445,1448],{"class":146,"line":626},[144,1436,1437],{"class":257},"        f",[144,1439,447],{"class":158},[144,1441,677],{"class":154},[144,1443,1444],{"class":158},"/videos/generations\"",[144,1446,1447],{"class":261},",  ",[144,1449,1450],{"class":173},"# 動画生成エンドポイント\n",[144,1452,1453,1456,1458,1460,1463],{"class":146,"line":637},[144,1454,1455],{"class":699},"        headers",[144,1457,265],{"class":257},[144,1459,421],{"class":154},[144,1461,1462],{"class":261},",                   ",[144,1464,1465],{"class":173},"# 認証 + content-type ヘッダー\n",[144,1467,1468,1471,1473,1476],{"class":146,"line":652},[144,1469,1470],{"class":699},"        json",[144,1472,265],{"class":257},[144,1474,1475],{"class":261},"payload                       ",[144,1477,1478],{"class":173},"# 自動的に JSON にシリアライズ\n",[144,1480,1481],{"class":146,"line":658},[144,1482,1483],{"class":261},"    )\n",[144,1485,1486,1489],{"class":146,"line":669},[144,1487,1488],{"class":261},"    response.raise_for_status()            ",[144,1490,1491],{"class":173},"# 200 以外なら例外を発生\n",[144,1493,1494,1497,1499,1502],{"class":146,"line":696},[144,1495,1496],{"class":261},"    task ",[144,1498,265],{"class":257},[144,1500,1501],{"class":261}," response.json()                 ",[144,1503,1504],{"class":173},"# JSON レスポンスをパース\n",[144,1506,1507],{"class":146,"line":708},[144,1508,374],{"emptyLinePlaceholder":57},[144,1510,1511],{"class":146,"line":714},[144,1512,1513],{"class":173},"    # レスポンスの主要情報を出力\n",[144,1515,1516,1518,1520,1522,1525,1527,1530,1533,1536,1538,1540],{"class":146,"line":720},[144,1517,1101],{"class":154},[144,1519,792],{"class":261},[144,1521,438],{"class":257},[144,1523,1524],{"class":158},"\"Task created: ",[144,1526,683],{"class":154},[144,1528,1529],{"class":261},"task[",[144,1531,1532],{"class":158},"'id'",[144,1534,1535],{"class":261},"]",[144,1537,689],{"class":154},[144,1539,447],{"class":158},[144,1541,404],{"class":261},[144,1543,1544,1546,1548,1550,1553,1555,1557,1560,1563,1566,1568,1570,1572],{"class":146,"line":726},[144,1545,1101],{"class":154},[144,1547,792],{"class":261},[144,1549,438],{"class":257},[144,1551,1552],{"class":158},"\"Estimated time: ",[144,1554,683],{"class":154},[144,1556,1529],{"class":261},[144,1558,1559],{"class":158},"'task_info'",[144,1561,1562],{"class":261},"][",[144,1564,1565],{"class":158},"'estimated_time'",[144,1567,1535],{"class":261},[144,1569,689],{"class":154},[144,1571,1023],{"class":158},[144,1573,404],{"class":261},[144,1575,1576,1578,1580,1582,1585,1587,1589,1592,1594,1597,1599,1601,1603],{"class":146,"line":737},[144,1577,1101],{"class":154},[144,1579,792],{"class":261},[144,1581,438],{"class":257},[144,1583,1584],{"class":158},"\"Credits reserved: ",[144,1586,683],{"class":154},[144,1588,1529],{"class":261},[144,1590,1591],{"class":158},"'usage'",[144,1593,1562],{"class":261},[144,1595,1596],{"class":158},"'credits_reserved'",[144,1598,1535],{"class":261},[144,1600,689],{"class":154},[144,1602,447],{"class":158},[144,1604,404],{"class":261},[144,1606,1607],{"class":146,"line":742},[144,1608,374],{"emptyLinePlaceholder":57},[144,1610,1611],{"class":146,"line":748},[144,1612,1613],{"class":173},"    # 動画が準備できるまで polling\n",[144,1615,1616,1619,1621,1624,1627],{"class":146,"line":765},[144,1617,1618],{"class":261},"    result ",[144,1620,265],{"class":257},[144,1622,1623],{"class":261}," wait_for_video(task[",[144,1625,1626],{"class":158},"\"id\"",[144,1628,1629],{"class":261},"])\n",[144,1631,1632],{"class":146,"line":786},[144,1633,374],{"emptyLinePlaceholder":57},[144,1635,1636],{"class":146,"line":832},[144,1637,1638],{"class":173},"    # results 配列に 1 つ以上の動画 URL が含まれる\n",[144,1640,1641,1644,1646,1649,1652,1654,1656],{"class":146,"line":837},[144,1642,1643],{"class":261},"    video_url ",[144,1645,265],{"class":257},[144,1647,1648],{"class":261}," result[",[144,1650,1651],{"class":158},"\"results\"",[144,1653,1562],{"class":261},[144,1655,781],{"class":154},[144,1657,762],{"class":261},[144,1659,1660,1662,1664,1666,1668,1671,1674,1676,1679,1681,1683],{"class":146,"line":843},[144,1661,1101],{"class":154},[144,1663,792],{"class":261},[144,1665,438],{"class":257},[144,1667,447],{"class":158},[144,1669,1670],{"class":154},"\\n",[144,1672,1673],{"class":158},"Video URL: ",[144,1675,683],{"class":154},[144,1677,1678],{"class":261},"video_url",[144,1680,689],{"class":154},[144,1682,447],{"class":158},[144,1684,404],{"class":261},[144,1686,1687,1690,1693],{"class":146,"line":861},[144,1688,1689],{"class":261},"    download_video(video_url, ",[144,1691,1692],{"class":158},"\"my_first_video.mp4\"",[144,1694,404],{"class":261},[144,1696,1697],{"class":146,"line":870},[144,1698,374],{"emptyLinePlaceholder":57},[144,1700,1701,1704],{"class":146,"line":885},[144,1702,1703],{"class":257},"    return",[144,1705,1706],{"class":261}," result\n",[144,1708,1709],{"class":146,"line":901},[144,1710,374],{"emptyLinePlaceholder":57},[144,1712,1713],{"class":146,"line":913},[144,1714,374],{"emptyLinePlaceholder":57},[144,1716,1717,1720,1723,1726,1729],{"class":146,"line":952},[144,1718,1719],{"class":257},"if",[144,1721,1722],{"class":154}," __name__",[144,1724,1725],{"class":257}," ==",[144,1727,1728],{"class":158}," \"__main__\"",[144,1730,858],{"class":261},[144,1732,1733],{"class":146,"line":958},[144,1734,1735],{"class":261},"    text_to_video()\n",[10,1737,1738],{},"payload の各パラメータを解説します：",[95,1740,1741,1756,1769,1777,1797,1817],{},[72,1742,1743,1748,1749,1752,1753,1755],{},[22,1744,1745],{},[27,1746,1747],{},"model"," — 使用する Seedance モデル。最新版は ",[27,1750,1751],{},"seedance-2.0"," に設定。お住まいの地域で 2.0 がまだ利用できない場合は ",[27,1754,29],{}," を使用してください。",[72,1757,1758,1763,1764,1768],{},[22,1759,1760],{},[27,1761,1762],{},"prompt"," — 動画の説明。主体、アクション、カメラの動き、雰囲気を具体的に記述してください。上記のプロンプトは 3 部構成：主体（\"golden retriever puppy\"）、アクション（\"chases a butterfly\"）、カメラ（\"smooth tracking shot\"）。高度なプロンプト技法は",[36,1765,1767],{"href":1766},"/blog/seedance-2-prompt-guide","プロンプトエンジニアリングガイド","を参照してください。",[72,1770,1771,1776],{},[22,1772,1773],{},[27,1774,1775],{},"duration"," — 動画の長さ（秒、4〜15）。短い動画ほど生成が速く、クレジット消費も少なくなります。テストには 5 秒がおすすめです。",[72,1778,1779,1784,1785,1788,1789,1792,1793,1796],{},[22,1780,1781],{},[27,1782,1783],{},"quality"," — 解像度ティア。",[27,1786,1787],{},"720p"," は開発段階での品質と速度の最適なバランスです。",[27,1790,1791],{},"480p"," は高速イテレーション向け、",[27,1794,1795],{},"1080p"," は最終レンダリング向け。",[72,1798,1799,1804,1805,1808,1809,1812,1813,1816],{},[22,1800,1801],{},[27,1802,1803],{},"aspect_ratio"," — 出力アスペクト比。",[27,1806,1807],{},"16:9"," は YouTube/横向き、",[27,1810,1811],{},"9:16"," は TikTok/Reels/Shorts、",[27,1814,1815],{},"1:1"," は Instagram フィード向け。",[72,1818,1819,1060,1824,1827],{},[22,1820,1821],{},[27,1822,1823],{},"generate_audio",[27,1825,1826],{},"true"," にすると、Seedance がビジュアルコンテンツにマッチする環境音と音楽を生成します。生成時間が約 2 秒追加されます。",[10,1829,1830],{},"実行：",[135,1832,1834],{"className":137,"code":1833,"language":139,"meta":140,"style":140},"python seedance_tutorial.py\n",[27,1835,1836],{"__ignoreMap":140},[144,1837,1838,1840],{"class":146,"line":147},[144,1839,338],{"class":150},[144,1841,1842],{"class":158}," seedance_tutorial.py\n",[91,1844,1846],{"id":1845},"api-のレスポンス内容","API のレスポンス内容",[10,1848,1849,1850,1853],{},"生成リクエストを送信すると、即座に ",[22,1851,1852],{},"task オブジェクト","が返されます — 動画はまだ準備できていません。実際のレスポンスは以下の通りです：",[135,1855,1859],{"className":1856,"code":1857,"language":1858,"meta":140,"style":140},"language-json shiki shiki-themes github-dark","{\n  \"created\": 1772203771,\n  \"id\": \"task-unified-1772203771-yf1dxogh\",\n  \"model\": \"seedance-2.0\",\n  \"object\": \"video.generation.task\",\n  \"progress\": 0,\n  \"status\": \"pending\",\n  \"task_info\": {\n    \"can_cancel\": true,\n    \"estimated_time\": 132\n  },\n  \"type\": \"video\",\n  \"usage\": {\n    \"billing_rule\": \"per_second\",\n    \"credits_reserved\": 17.784,\n    \"user_group\": \"default\"\n  }\n}\n","json",[27,1860,1861,1866,1878,1890,1901,1913,1924,1936,1944,1955,1965,1970,1982,1989,2001,2013,2023,2028],{"__ignoreMap":140},[144,1862,1863],{"class":146,"line":147},[144,1864,1865],{"class":261},"{\n",[144,1867,1868,1871,1873,1876],{"class":146,"line":165},[144,1869,1870],{"class":154},"  \"created\"",[144,1872,435],{"class":261},[144,1874,1875],{"class":154},"1772203771",[144,1877,450],{"class":261},[144,1879,1880,1883,1885,1888],{"class":146,"line":177},[144,1881,1882],{"class":154},"  \"id\"",[144,1884,435],{"class":261},[144,1886,1887],{"class":158},"\"task-unified-1772203771-yf1dxogh\"",[144,1889,450],{"class":261},[144,1891,1892,1895,1897,1899],{"class":146,"line":186},[144,1893,1894],{"class":154},"  \"model\"",[144,1896,435],{"class":261},[144,1898,1308],{"class":158},[144,1900,450],{"class":261},[144,1902,1903,1906,1908,1911],{"class":146,"line":371},[144,1904,1905],{"class":154},"  \"object\"",[144,1907,435],{"class":261},[144,1909,1910],{"class":158},"\"video.generation.task\"",[144,1912,450],{"class":261},[144,1914,1915,1918,1920,1922],{"class":146,"line":377},[144,1916,1917],{"class":154},"  \"progress\"",[144,1919,435],{"class":261},[144,1921,781],{"class":154},[144,1923,450],{"class":261},[144,1925,1926,1929,1931,1934],{"class":146,"line":383},[144,1927,1928],{"class":154},"  \"status\"",[144,1930,435],{"class":261},[144,1932,1933],{"class":158},"\"pending\"",[144,1935,450],{"class":261},[144,1937,1938,1941],{"class":146,"line":407},[144,1939,1940],{"class":154},"  \"task_info\"",[144,1942,1943],{"class":261},": {\n",[144,1945,1946,1949,1951,1953],{"class":146,"line":418},[144,1947,1948],{"class":154},"    \"can_cancel\"",[144,1950,435],{"class":261},[144,1952,1826],{"class":154},[144,1954,450],{"class":261},[144,1956,1957,1960,1962],{"class":146,"line":429},[144,1958,1959],{"class":154},"    \"estimated_time\"",[144,1961,435],{"class":261},[144,1963,1964],{"class":154},"132\n",[144,1966,1967],{"class":146,"line":453},[144,1968,1969],{"class":261},"  },\n",[144,1971,1972,1975,1977,1980],{"class":146,"line":464},[144,1973,1974],{"class":154},"  \"type\"",[144,1976,435],{"class":261},[144,1978,1979],{"class":158},"\"video\"",[144,1981,450],{"class":261},[144,1983,1984,1987],{"class":146,"line":598},[144,1985,1986],{"class":154},"  \"usage\"",[144,1988,1943],{"class":261},[144,1990,1991,1994,1996,1999],{"class":146,"line":603},[144,1992,1993],{"class":154},"    \"billing_rule\"",[144,1995,435],{"class":261},[144,1997,1998],{"class":158},"\"per_second\"",[144,2000,450],{"class":261},[144,2002,2003,2006,2008,2011],{"class":146,"line":609},[144,2004,2005],{"class":154},"    \"credits_reserved\"",[144,2007,435],{"class":261},[144,2009,2010],{"class":154},"17.784",[144,2012,450],{"class":261},[144,2014,2015,2018,2020],{"class":146,"line":615},[144,2016,2017],{"class":154},"    \"user_group\"",[144,2019,435],{"class":261},[144,2021,2022],{"class":158},"\"default\"\n",[144,2024,2025],{"class":146,"line":621},[144,2026,2027],{"class":261},"  }\n",[144,2029,2030],{"class":146,"line":626},[144,2031,467],{"class":261},[10,2033,2034],{},"主要フィールドの説明：",[2036,2037,2038,2051],"table",{},[2039,2040,2041],"thead",{},[2042,2043,2044,2048],"tr",{},[2045,2046,2047],"th",{},"フィールド",[2045,2049,2050],{},"意味",[2052,2053,2054,2065,2089,2101,2111,2121,2133,2143],"tbody",{},[2042,2055,2056,2062],{},[2057,2058,2059],"td",{},[27,2060,2061],{},"id",[2057,2063,2064],{},"タスク ID — ステータス確認と結果取得に使用",[2042,2066,2067,2071],{},[2057,2068,2069],{},[27,2070,812],{},[2057,2072,2073,2076,2077,2080,2081,2084,2085,2088],{},[27,2074,2075],{},"pending"," で開始、",[27,2078,2079],{},"processing"," を経て ",[27,2082,2083],{},"completed"," または ",[27,2086,2087],{},"failed"," に変化",[2042,2090,2091,2095],{},[2057,2092,2093],{},[27,2094,822],{},[2057,2096,2097,2098,2100],{},"0〜100 のパーセンテージ。",[27,2099,2079],{}," フェーズでリアルタイム更新",[2042,2102,2103,2108],{},[2057,2104,2105],{},[27,2106,2107],{},"estimated_time",[2057,2109,2110],{},"推定完了時間（秒）、サーバー側の見積もり",[2042,2112,2113,2118],{},[2057,2114,2115],{},[27,2116,2117],{},"credits_reserved",[2057,2119,2120],{},"このジョブに予約されたクレジット。タスク失敗時は自動返金",[2042,2122,2123,2128],{},[2057,2124,2125],{},[27,2126,2127],{},"task_info.can_cancel",[2057,2129,2130,2131,116],{},"タスクをキャンセルできるか（完了前は常に ",[27,2132,1826],{},[2042,2134,2135,2140],{},[2057,2136,2137],{},[27,2138,2139],{},"created",[2057,2141,2142],{},"タスク送信時の Unix タイムスタンプ",[2042,2144,2145,2150],{},[2057,2146,2147],{},[27,2148,2149],{},"usage.billing_rule",[2057,2151,2152,2153,2156],{},"課金方式 — ",[27,2154,2155],{},"per_second"," は動画の長さに応じた従量課金",[17,2158,2159],{},[10,2160,2161,2163,2164,2166,2167,2170],{},[22,2162,132],{}," 送信後すぐに ",[27,2165,2061],{}," をファイルやデータベースに保存してください。polling 中にスクリプトがクラッシュした場合、保存したタスク ID で ",[27,2168,2169],{},"wait_for_video()"," を呼び出して復旧できます。タスクはサーバーに 24 時間保持されます。",[91,2172,2174],{"id":2173},"polling-の流れ","Polling の流れ",[10,2176,2177,2179],{},[27,2178,2169],{}," 関数は 10 秒ごとに polling します。実際の出力は以下の通りです：",[135,2181,2186],{"className":2182,"code":2184,"language":2185},[2183],"language-text","Submitting text-to-video request...\nTask created: task-unified-1772203771-yf1dxogh\nEstimated time: 132s\nCredits reserved: 17.784\n  [0s] Status: pending | Progress: 0%\n  [10s] Status: processing | Progress: 7%\n  [20s] Status: processing | Progress: 13%\n  [30s] Status: processing | Progress: 20%\n  [40s] Status: processing | Progress: 27%\n  [50s] Status: completed | Progress: 100%\n\nVideo URL: https://files.evolink.ai/.../cgt-20260227224931-8vl7s.mp4\nDownloading video to my_first_video.mp4...\nSaved: my_first_video.mp4 (2847 KB)\n","text",[27,2187,2184],{"__ignoreMap":140},[10,2189,2190],{},"これだけです — API コールから動画ファイルの保存まで約 50 秒。",[17,2192,2193],{},[10,2194,2195,2198],{},[22,2196,2197],{},"重要："," 動画 URL は 24 時間後に期限切れになります。必ず速やかにファイルをダウンロードするか、自前のストレージ（S3、GCS、Cloudflare R2 など）に保存してください。",[17,2200,2201],{},[10,2202,2203,2205],{},[22,2204,303],{}," 動画 URL を長期保存に使わないでください。パイプラインは生成完了後すぐにダウンロードするように構築してください。非同期で動画を処理する場合は、webhook（後述）を使って準備完了の瞬間にダウンロードをトリガーしてください。",[10,2207,2208,2209,2212],{},"効果的なプロンプトの書き方は ",[36,2210,2211],{"href":1766},"Seedance 2.0 プロンプトガイド","を参照してください — ショットスクリプト形式、スタイルキーワード、タイミング構文を解説しています。",[44,2214],{},[47,2216,2218],{"id":2217},"結果の-polling非同期ワークフローを理解する","結果の Polling：非同期ワークフローを理解する",[10,2220,2221,2222,2225],{},"動画生成は長さと品質設定に応じて 30〜120 秒以上かかります。API は",[22,2223,2224],{},"非同期タスクパターン","を使用します — OpenAI、Stability AI など、ほとんどの生成 AI API と同じパターンです：",[69,2227,2228,2238,2248],{},[72,2229,2230,2233,2234,2237],{},[22,2231,2232],{},"送信"," → POST ",[27,2235,2236],{},"/v1/videos/generations"," → 即座にタスク ID を取得",[72,2239,2240,2243,2244,2247],{},[22,2241,2242],{},"Polling"," → GET ",[27,2245,2246],{},"/v1/tasks/{task_id}"," → 定期的にステータスを確認",[72,2249,2250,2253,2254,2257,2258,2261],{},[22,2251,2252],{},"取得"," → ",[27,2255,2256],{},"status: \"completed\""," のとき、",[27,2259,2260],{},"results"," 配列に動画 URL が含まれる",[10,2263,2264],{},"このパターンが存在する理由は、動画生成には膨大な計算リソースが必要だからです。同期 HTTP リクエストでは、動画の生成完了よりはるか前にタイムアウトしてしまいます。",[91,2266,2267],{"id":2267},"タスクステータスのライフサイクル",[135,2269,2272],{"className":2270,"code":2271,"language":2185},[2183],"pending → processing → completed\n                    ↘ failed\n",[27,2273,2271],{"__ignoreMap":140},[2036,2275,2276,2289],{},[2039,2277,2278],{},[2042,2279,2280,2283,2286],{},[2045,2281,2282],{},"ステータス",[2045,2284,2285],{},"何が起きているか",[2045,2287,2288],{},"一般的な所要時間",[2052,2290,2291,2303,2318,2333],{},[2042,2292,2293,2297,2300],{},[2057,2294,2295],{},[27,2296,2075],{},[2057,2298,2299],{},"タスクがキューで待機中、GPU リソース待ち",[2057,2301,2302],{},"0〜30 秒",[2042,2304,2305,2309,2315],{},[2057,2306,2307],{},[27,2308,2079],{},[2057,2310,2311,2312,2314],{},"動画を生成中 — ",[27,2313,822],{}," がリアルタイム更新",[2057,2316,2317],{},"30〜120 秒",[2042,2319,2320,2324,2330],{},[2057,2321,2322],{},[27,2323,2083],{},[2057,2325,2326,2327,2329],{},"完了！",[27,2328,2260],{}," 配列に動画 URL あり",[2057,2331,2332],{},"終了状態",[2042,2334,2335,2339,2342],{},[2057,2336,2337],{},[27,2338,2087],{},[2057,2340,2341],{},"エラー発生 — エラー詳細を確認",[2057,2343,2332],{},[91,2345,2347],{"id":2346},"polling-のベストプラクティス","Polling のベストプラクティス",[10,2349,2350,2353],{},[22,2351,2352],{},"Polling 間隔："," 10 秒が適切なデフォルトです。速すぎるとリクエストを浪費してレート制限をトリガーする可能性があり、遅すぎるとパイプラインが遅延します。リアルタイム性が求められるアプリケーションでは 5 秒ごとに polling できますが、それ以上速くする必要はありません。",[10,2355,2356,2359],{},[22,2357,2358],{},"タイムアウト："," パラメータに応じて合理的な上限を設定してください：",[2036,2361,2362,2375],{},[2039,2363,2364],{},[2042,2365,2366,2369,2372],{},[2045,2367,2368],{},"設定",[2045,2370,2371],{},"予想所要時間",[2045,2373,2374],{},"推奨タイムアウト",[2052,2376,2377,2388,2399,2410],{},[2042,2378,2379,2382,2385],{},[2057,2380,2381],{},"4s, 480p",[2057,2383,2384],{},"20〜40 秒",[2057,2386,2387],{},"120 秒",[2042,2389,2390,2393,2396],{},[2057,2391,2392],{},"5s, 720p",[2057,2394,2395],{},"30〜60 秒",[2057,2397,2398],{},"180 秒",[2042,2400,2401,2404,2407],{},[2057,2402,2403],{},"10s, 720p",[2057,2405,2406],{},"60〜90 秒",[2057,2408,2409],{},"300 秒",[2042,2411,2412,2415,2418],{},[2057,2413,2414],{},"15s, 1080p",[2057,2416,2417],{},"90〜180 秒",[2057,2419,2420],{},"600 秒",[10,2422,2423,2426,2427,2429,2430,2432],{},[22,2424,2425],{},"進捗トラッキング："," ",[27,2428,822],{}," フィールド（0〜100）は細かいフィードバックを提供します — UI でプログレスバーを構築するのに便利です。",[27,2431,2079],{}," フェーズ中、約 5〜7 秒ごとに更新されます。",[91,2434,2435],{"id":2435},"タスクのキャンセル",[10,2437,2438],{},"進行中の生成を停止する必要がある場合（プロンプトを間違えた、気が変わった）、キャンセルできます：",[135,2440,2442],{"className":336,"code":2441,"language":338,"meta":140,"style":140},"def cancel_task(task_id):\n    \"\"\"pending または processing 状態のタスクをキャンセルします。クレジットは返金されます。\"\"\"\n    response = requests.post(\n        f\"{BASE_URL}/tasks/{task_id}/cancel\",\n        headers=HEADERS\n    )\n    if response.status_code == 200:\n        print(f\"Task {task_id} cancelled. Credits refunded.\")\n    else:\n        print(f\"Cancel failed: {response.json()}\")\n",[27,2443,2444,2454,2459,2467,2488,2496,2500,2515,2536,2543],{"__ignoreMap":140},[144,2445,2446,2448,2451],{"class":146,"line":147},[144,2447,524],{"class":257},[144,2449,2450],{"class":150}," cancel_task",[144,2452,2453],{"class":261},"(task_id):\n",[144,2455,2456],{"class":146,"line":165},[144,2457,2458],{"class":158},"    \"\"\"pending または processing 状態のタスクをキャンセルします。クレジットは返金されます。\"\"\"\n",[144,2460,2461,2463,2465],{"class":146,"line":177},[144,2462,1427],{"class":261},[144,2464,265],{"class":257},[144,2466,1432],{"class":261},[144,2468,2469,2471,2473,2475,2477,2479,2481,2483,2486],{"class":146,"line":186},[144,2470,1437],{"class":257},[144,2472,447],{"class":158},[144,2474,677],{"class":154},[144,2476,680],{"class":158},[144,2478,683],{"class":154},[144,2480,686],{"class":261},[144,2482,689],{"class":154},[144,2484,2485],{"class":158},"/cancel\"",[144,2487,450],{"class":261},[144,2489,2490,2492,2494],{"class":146,"line":371},[144,2491,1455],{"class":699},[144,2493,265],{"class":257},[144,2495,705],{"class":154},[144,2497,2498],{"class":146,"line":377},[144,2499,1483],{"class":261},[144,2501,2502,2505,2508,2510,2513],{"class":146,"line":383},[144,2503,2504],{"class":257},"    if",[144,2506,2507],{"class":261}," response.status_code ",[144,2509,852],{"class":257},[144,2511,2512],{"class":154}," 200",[144,2514,858],{"class":261},[144,2516,2517,2519,2521,2523,2525,2527,2529,2531,2534],{"class":146,"line":407},[144,2518,789],{"class":154},[144,2520,792],{"class":261},[144,2522,438],{"class":257},[144,2524,919],{"class":158},[144,2526,683],{"class":154},[144,2528,686],{"class":261},[144,2530,689],{"class":154},[144,2532,2533],{"class":158}," cancelled. Credits refunded.\"",[144,2535,404],{"class":261},[144,2537,2538,2541],{"class":146,"line":418},[144,2539,2540],{"class":257},"    else",[144,2542,858],{"class":261},[144,2544,2545,2547,2549,2551,2554,2556,2559,2561,2563],{"class":146,"line":429},[144,2546,789],{"class":154},[144,2548,792],{"class":261},[144,2550,438],{"class":257},[144,2552,2553],{"class":158},"\"Cancel failed: ",[144,2555,683],{"class":154},[144,2557,2558],{"class":261},"response.json()",[144,2560,689],{"class":154},[144,2562,447],{"class":158},[144,2564,404],{"class":261},[10,2566,2567,2568,2570,2571,2573,2574,2084,2576,2578],{},"キャンセルは ",[27,2569,2127],{}," が ",[27,2572,1826],{}," のときに有効です。タスクが ",[27,2575,2083],{},[27,2577,2087],{}," に達した後はキャンセルできません。キャンセル時に予約されたクレジットは自動的に返金されます。",[17,2580,2581],{},[10,2582,2583,2585],{},[22,2584,132],{}," UI にキャンセル機能を早めに組み込んでください。ユーザーは必ず間違ったプロンプトを送信します。不要な動画を 2 分待つのは時間とクレジットの無駄です。",[10,2587,2588,2589,2591,2592,2596],{},"前述の ",[27,2590,2169],{}," 関数が標準的な polling フローを処理します。polling を完全にスキップしたい場合は、下の ",[36,2593,2595],{"href":2594},"#webhook-%E3%81%AE%E8%A8%AD%E5%AE%9Apolling-%E3%82%92%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97","Webhook セクション","に進んでください。",[44,2598],{},[47,2600,2602],{"id":2601},"画像をアニメーション化する画像から動画","画像をアニメーション化する（画像から動画）",[10,2604,2605,2606,2609,2610,2614],{},"商品写真やキャラクターイラスト、風景写真に動きをつけたいですか？",[27,2607,2608],{},"image_url"," として渡せば、Seedance がアニメーション化します。",[36,2611,2613],{"href":2612},"/blog/seedance-2-ecommerce-product-videos","EC 商品動画","で最も強力な機能の 1 つです — 静的な商品写真を魅力的な動画広告に変換します。",[10,2616,2617],{},[2618,2619,2620],"em",{},"上記の最初の例と同じセットアップと polling 関数を使用します。",[135,2622,2624],{"className":336,"code":2623,"language":338,"meta":140,"style":140},"# ── 画像から動画 ──────────────────────────────────────────────\ndef image_to_video():\n    payload = {\n        \"model\": \"seedance-2.0\",\n        \"prompt\": (\n            \"@Image1 as the first frame. The scene slowly comes \"\n            \"to life — leaves rustle gently, soft light shifts \"\n            \"across the frame, and the subject blinks naturally.\"\n        ),\n        \"image_urls\": [\n            \"https://example.com/your-image.jpg\"\n        ],\n        \"duration\": 5,\n        \"quality\": \"720p\",\n        \"aspect_ratio\": \"16:9\"\n    }\n\n    print(\"Submitting image-to-video request...\")\n    response = requests.post(\n        f\"{BASE_URL}/videos/generations\",\n        headers=HEADERS,\n        json=payload\n    )\n    response.raise_for_status()\n    task = response.json()\n\n    print(f\"Task created: {task['id']}\")\n    result = wait_for_video(task[\"id\"])\n\n    video_url = result[\"results\"][0]\n    download_video(video_url, \"animated_image.mp4\")\n\n    return result\n",[27,2625,2626,2631,2640,2648,2658,2664,2669,2674,2679,2683,2691,2696,2701,2711,2721,2730,2734,2738,2749,2757,2769,2779,2788,2792,2797,2805,2809,2833,2845,2849,2865,2874,2878],{"__ignoreMap":140},[144,2627,2628],{"class":146,"line":147},[144,2629,2630],{"class":173},"# ── 画像から動画 ──────────────────────────────────────────────\n",[144,2632,2633,2635,2638],{"class":146,"line":165},[144,2634,524],{"class":257},[144,2636,2637],{"class":150}," image_to_video",[144,2639,1289],{"class":261},[144,2641,2642,2644,2646],{"class":146,"line":177},[144,2643,1294],{"class":261},[144,2645,265],{"class":257},[144,2647,426],{"class":261},[144,2649,2650,2652,2654,2656],{"class":146,"line":186},[144,2651,1303],{"class":158},[144,2653,435],{"class":261},[144,2655,1308],{"class":158},[144,2657,450],{"class":261},[144,2659,2660,2662],{"class":146,"line":371},[144,2661,1319],{"class":158},[144,2663,1322],{"class":261},[144,2665,2666],{"class":146,"line":377},[144,2667,2668],{"class":158},"            \"@Image1 as the first frame. The scene slowly comes \"\n",[144,2670,2671],{"class":146,"line":383},[144,2672,2673],{"class":158},"            \"to life — leaves rustle gently, soft light shifts \"\n",[144,2675,2676],{"class":146,"line":407},[144,2677,2678],{"class":158},"            \"across the frame, and the subject blinks naturally.\"\n",[144,2680,2681],{"class":146,"line":418},[144,2682,1342],{"class":261},[144,2684,2685,2688],{"class":146,"line":429},[144,2686,2687],{"class":158},"        \"image_urls\"",[144,2689,2690],{"class":261},": [\n",[144,2692,2693],{"class":146,"line":453},[144,2694,2695],{"class":158},"            \"https://example.com/your-image.jpg\"\n",[144,2697,2698],{"class":146,"line":464},[144,2699,2700],{"class":261},"        ],\n",[144,2702,2703,2705,2707,2709],{"class":146,"line":598},[144,2704,1347],{"class":158},[144,2706,435],{"class":261},[144,2708,1352],{"class":154},[144,2710,450],{"class":261},[144,2712,2713,2715,2717,2719],{"class":146,"line":603},[144,2714,1363],{"class":158},[144,2716,435],{"class":261},[144,2718,1368],{"class":158},[144,2720,450],{"class":261},[144,2722,2723,2725,2727],{"class":146,"line":609},[144,2724,1379],{"class":158},[144,2726,435],{"class":261},[144,2728,2729],{"class":158},"\"16:9\"\n",[144,2731,2732],{"class":146,"line":615},[144,2733,1407],{"class":261},[144,2735,2736],{"class":146,"line":621},[144,2737,374],{"emptyLinePlaceholder":57},[144,2739,2740,2742,2744,2747],{"class":146,"line":626},[144,2741,1101],{"class":154},[144,2743,792],{"class":261},[144,2745,2746],{"class":158},"\"Submitting image-to-video request...\"",[144,2748,404],{"class":261},[144,2750,2751,2753,2755],{"class":146,"line":637},[144,2752,1427],{"class":261},[144,2754,265],{"class":257},[144,2756,1432],{"class":261},[144,2758,2759,2761,2763,2765,2767],{"class":146,"line":652},[144,2760,1437],{"class":257},[144,2762,447],{"class":158},[144,2764,677],{"class":154},[144,2766,1444],{"class":158},[144,2768,450],{"class":261},[144,2770,2771,2773,2775,2777],{"class":146,"line":658},[144,2772,1455],{"class":699},[144,2774,265],{"class":257},[144,2776,421],{"class":154},[144,2778,450],{"class":261},[144,2780,2781,2783,2785],{"class":146,"line":669},[144,2782,1470],{"class":699},[144,2784,265],{"class":257},[144,2786,2787],{"class":261},"payload\n",[144,2789,2790],{"class":146,"line":696},[144,2791,1483],{"class":261},[144,2793,2794],{"class":146,"line":708},[144,2795,2796],{"class":261},"    response.raise_for_status()\n",[144,2798,2799,2801,2803],{"class":146,"line":714},[144,2800,1496],{"class":261},[144,2802,265],{"class":257},[144,2804,734],{"class":261},[144,2806,2807],{"class":146,"line":720},[144,2808,374],{"emptyLinePlaceholder":57},[144,2810,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829,2831],{"class":146,"line":726},[144,2812,1101],{"class":154},[144,2814,792],{"class":261},[144,2816,438],{"class":257},[144,2818,1524],{"class":158},[144,2820,683],{"class":154},[144,2822,1529],{"class":261},[144,2824,1532],{"class":158},[144,2826,1535],{"class":261},[144,2828,689],{"class":154},[144,2830,447],{"class":158},[144,2832,404],{"class":261},[144,2834,2835,2837,2839,2841,2843],{"class":146,"line":737},[144,2836,1618],{"class":261},[144,2838,265],{"class":257},[144,2840,1623],{"class":261},[144,2842,1626],{"class":158},[144,2844,1629],{"class":261},[144,2846,2847],{"class":146,"line":742},[144,2848,374],{"emptyLinePlaceholder":57},[144,2850,2851,2853,2855,2857,2859,2861,2863],{"class":146,"line":748},[144,2852,1643],{"class":261},[144,2854,265],{"class":257},[144,2856,1648],{"class":261},[144,2858,1651],{"class":158},[144,2860,1562],{"class":261},[144,2862,781],{"class":154},[144,2864,762],{"class":261},[144,2866,2867,2869,2872],{"class":146,"line":765},[144,2868,1689],{"class":261},[144,2870,2871],{"class":158},"\"animated_image.mp4\"",[144,2873,404],{"class":261},[144,2875,2876],{"class":146,"line":786},[144,2877,374],{"emptyLinePlaceholder":57},[144,2879,2880,2882],{"class":146,"line":832},[144,2881,1703],{"class":257},[144,2883,1706],{"class":261},[10,2885,2886],{},"テキストから動画との違いを見てみましょう：",[95,2888,2889,2901,2923],{},[72,2890,2891,2896,2897,2900],{},[22,2892,2893],{},[27,2894,2895],{},"image_urls"," — 公開アクセス可能な画像 URL の配列です。API が直接取得するため、インターネットからアクセスできる必要があります（",[27,2898,2899],{},"localhost"," やプライベートネットワーク URL は不可）。",[72,2902,2903,2909,2910,2912,2913,2915,2916,2915,2919,2922],{},[22,2904,2905,2906],{},"プロンプト内の ",[27,2907,2908],{},"@Image1"," — このタグは Seedance にどの画像をどう参照するかを伝えます。",[27,2911,2895],{}," の最初の URL に対応します。3 枚の画像を渡す場合は ",[27,2914,2908],{},"、",[27,2917,2918],{},"@Image2",[27,2920,2921],{},"@Image3"," を使います。",[72,2924,2925,2930,2931,2933,2934,2937],{},[22,2926,2927,2929],{},[27,2928,1823],{}," なし"," — ここでは省略しており、デフォルトは ",[27,2932,1826],{}," です。無音アニメーションにするには ",[27,2935,2936],{},"false"," に設定してください。",[91,2939,2941],{"id":2940},"image-タグの仕組み","@Image タグの仕組み",[10,2943,2905,2944,2946,2947,2949,2950,2952,2953,2956,2957,279,2960,2963,2964,1768],{},[27,2945,2908],{}," タグは、Seedance に画像の使い方を伝えます。",[27,2948,2895],{}," 配列の最初の URL を参照します。最大 9 枚の画像を渡せます（",[27,2951,2908],{}," から ",[27,2954,2955],{},"@Image9"," まで）。",[27,2958,2959],{},"@Video",[27,2961,2962],{},"@Audio"," を含むマルチモーダルタグの完全ガイドは",[36,2965,2967],{"href":2966},"/blog/seedance-2-multimodal-tags-guide","マルチモーダル @Tags ガイド",[10,2969,2970],{},"よく使うパターン：",[2036,2972,2973,2986],{},[2039,2974,2975],{},[2042,2976,2977,2980,2983],{},[2045,2978,2979],{},"プロンプトパターン",[2045,2981,2982],{},"効果",[2045,2984,2985],{},"適した用途",[2052,2987,2988,3001,3014,3027,3040],{},[2042,2989,2990,2995,2998],{},[2057,2991,2992],{},[27,2993,2994],{},"@Image1 as first frame",[2057,2996,2997],{},"画像を開始フレームとして使用",[2057,2999,3000],{},"商品ショーケース、シーン設定",[2042,3002,3003,3008,3011],{},[2057,3004,3005],{},[27,3006,3007],{},"@Image1 as last frame",[2057,3009,3010],{},"画像を最終フレームとして使用",[2057,3012,3013],{},"ロゴ公開、トランジション",[2042,3015,3016,3021,3024],{},[2057,3017,3018],{},[27,3019,3020],{},"@Image1 as character reference",[2057,3022,3023],{},"キャラクターの外見を維持",[2057,3025,3026],{},"クリップ間のキャラクター一貫性",[2042,3028,3029,3034,3037],{},[2057,3030,3031],{},[27,3032,3033],{},"@Image1 as style reference",[2057,3035,3036],{},"画像のビジュアルスタイルを適用",[2057,3038,3039],{},"ブランド一貫性、アートディレクション",[2042,3041,3042,3047,3050],{},[2057,3043,3044],{},[27,3045,3046],{},"@Image1 as first frame, @Image2 as last frame",[2057,3048,3049],{},"2 枚の画像間のトランジションを作成",[2057,3051,3052],{},"ビフォーアフター、変形",[10,3054,3055],{},"テストで得た実際のレスポンス：",[135,3057,3059],{"className":1856,"code":3058,"language":1858,"meta":140,"style":140},"{\n  \"created\": 1772204037,\n  \"id\": \"task-unified-1772204036-lify8u5p\",\n  \"model\": \"seedance-2.0\",\n  \"object\": \"video.generation.task\",\n  \"progress\": 0,\n  \"status\": \"pending\",\n  \"task_info\": {\n    \"can_cancel\": true,\n    \"estimated_time\": 145\n  },\n  \"type\": \"video\",\n  \"usage\": {\n    \"billing_rule\": \"per_second\",\n    \"credits_reserved\": 17.784,\n    \"user_group\": \"default\"\n  }\n}\n",[27,3060,3061,3065,3076,3087,3097,3107,3117,3127,3133,3143,3152,3156,3166,3172,3182,3192,3200,3204],{"__ignoreMap":140},[144,3062,3063],{"class":146,"line":147},[144,3064,1865],{"class":261},[144,3066,3067,3069,3071,3074],{"class":146,"line":165},[144,3068,1870],{"class":154},[144,3070,435],{"class":261},[144,3072,3073],{"class":154},"1772204037",[144,3075,450],{"class":261},[144,3077,3078,3080,3082,3085],{"class":146,"line":177},[144,3079,1882],{"class":154},[144,3081,435],{"class":261},[144,3083,3084],{"class":158},"\"task-unified-1772204036-lify8u5p\"",[144,3086,450],{"class":261},[144,3088,3089,3091,3093,3095],{"class":146,"line":186},[144,3090,1894],{"class":154},[144,3092,435],{"class":261},[144,3094,1308],{"class":158},[144,3096,450],{"class":261},[144,3098,3099,3101,3103,3105],{"class":146,"line":371},[144,3100,1905],{"class":154},[144,3102,435],{"class":261},[144,3104,1910],{"class":158},[144,3106,450],{"class":261},[144,3108,3109,3111,3113,3115],{"class":146,"line":377},[144,3110,1917],{"class":154},[144,3112,435],{"class":261},[144,3114,781],{"class":154},[144,3116,450],{"class":261},[144,3118,3119,3121,3123,3125],{"class":146,"line":383},[144,3120,1928],{"class":154},[144,3122,435],{"class":261},[144,3124,1933],{"class":158},[144,3126,450],{"class":261},[144,3128,3129,3131],{"class":146,"line":407},[144,3130,1940],{"class":154},[144,3132,1943],{"class":261},[144,3134,3135,3137,3139,3141],{"class":146,"line":418},[144,3136,1948],{"class":154},[144,3138,435],{"class":261},[144,3140,1826],{"class":154},[144,3142,450],{"class":261},[144,3144,3145,3147,3149],{"class":146,"line":429},[144,3146,1959],{"class":154},[144,3148,435],{"class":261},[144,3150,3151],{"class":154},"145\n",[144,3153,3154],{"class":146,"line":453},[144,3155,1969],{"class":261},[144,3157,3158,3160,3162,3164],{"class":146,"line":464},[144,3159,1974],{"class":154},[144,3161,435],{"class":261},[144,3163,1979],{"class":158},[144,3165,450],{"class":261},[144,3167,3168,3170],{"class":146,"line":598},[144,3169,1986],{"class":154},[144,3171,1943],{"class":261},[144,3173,3174,3176,3178,3180],{"class":146,"line":603},[144,3175,1993],{"class":154},[144,3177,435],{"class":261},[144,3179,1998],{"class":158},[144,3181,450],{"class":261},[144,3183,3184,3186,3188,3190],{"class":146,"line":609},[144,3185,2005],{"class":154},[144,3187,435],{"class":261},[144,3189,2010],{"class":154},[144,3191,450],{"class":261},[144,3193,3194,3196,3198],{"class":146,"line":615},[144,3195,2017],{"class":154},[144,3197,435],{"class":261},[144,3199,2022],{"class":158},[144,3201,3202],{"class":146,"line":621},[144,3203,2027],{"class":261},[144,3205,3206],{"class":146,"line":626},[144,3207,467],{"class":261},[10,3209,3210,3211,3213],{},"画像から動画はテキストから動画とまったく同じ非同期パターンに従います — 送信、polling、ダウンロード。モデルが入力画像を分析する必要があるため、",[27,3212,2107],{}," はやや長くなります。",[91,3215,3216],{"id":3216},"画像の要件",[2036,3218,3219,3229],{},[2039,3220,3221],{},[2042,3222,3223,3226],{},[2045,3224,3225],{},"制約",[2045,3227,3228],{},"値",[2052,3230,3231,3239,3247,3255,3263],{},[2042,3232,3233,3236],{},[2057,3234,3235],{},"最大画像数",[2057,3237,3238],{},"リクエストあたり 9 枚",[2042,3240,3241,3244],{},[2057,3242,3243],{},"最大ファイルサイズ",[2057,3245,3246],{},"画像あたり 30 MB",[2042,3248,3249,3252],{},[2057,3250,3251],{},"対応フォーマット",[2057,3253,3254],{},"JPEG、PNG、WebP、BMP、TIFF、GIF",[2042,3256,3257,3260],{},[2057,3258,3259],{},"URL 要件",[2057,3261,3262],{},"公開アクセス可能であること",[2042,3264,3265,3268],{},[2057,3266,3267],{},"推奨解像度",[2057,3269,3270],{},"短辺 720px 以上",[17,3272,3273],{},[10,3274,3275,3277,3278,3280],{},[22,3276,303],{}," URL ではなくローカルファイルパスを渡すこと。",[27,3279,2895],{}," フィールドには公開アクセス可能な HTTP/HTTPS URL が必要です。画像がローカルにある場合は、まず S3、Cloudflare R2、または一時ファイルホスティングサービスにアップロードしてください。",[17,3282,3283],{},[10,3284,3285,3288],{},[22,3286,3287],{},"制限事項："," Seedance はリアルな人物の顔画像のアップロードをサポートしていません。システムが自動的に拒否します。イラストやスタイライズされたキャラクターを使用してください。",[91,3290,3292],{"id":3291},"api-用の画像ホスティング","API 用の画像ホスティング",[10,3294,3295],{},"CDN がない場合、公開 URL を素早く取得する方法：",[135,3297,3299],{"className":336,"code":3298,"language":338,"meta":140,"style":140},"# 方法 1：S3 にアップロード（AWS がある場合）\nimport boto3\ns3 = boto3.client('s3')\ns3.upload_file('local_image.jpg', 'my-bucket', 'seedance/input.jpg')\nimage_url = f\"https://my-bucket.s3.amazonaws.com/seedance/input.jpg\"\n\n# 方法 2：一時ファイルホスティング API を使用\n# 多くのサービスがテスト用の無料一時ホスティングを提供しています\n",[27,3300,3301,3306,3313,3328,3348,3361,3365,3370],{"__ignoreMap":140},[144,3302,3303],{"class":146,"line":147},[144,3304,3305],{"class":173},"# 方法 1：S3 にアップロード（AWS がある場合）\n",[144,3307,3308,3310],{"class":146,"line":165},[144,3309,345],{"class":257},[144,3311,3312],{"class":261}," boto3\n",[144,3314,3315,3318,3320,3323,3326],{"class":146,"line":177},[144,3316,3317],{"class":261},"s3 ",[144,3319,265],{"class":257},[144,3321,3322],{"class":261}," boto3.client(",[144,3324,3325],{"class":158},"'s3'",[144,3327,404],{"class":261},[144,3329,3330,3333,3336,3338,3341,3343,3346],{"class":146,"line":186},[144,3331,3332],{"class":261},"s3.upload_file(",[144,3334,3335],{"class":158},"'local_image.jpg'",[144,3337,398],{"class":261},[144,3339,3340],{"class":158},"'my-bucket'",[144,3342,398],{"class":261},[144,3344,3345],{"class":158},"'seedance/input.jpg'",[144,3347,404],{"class":261},[144,3349,3350,3353,3355,3358],{"class":146,"line":371},[144,3351,3352],{"class":261},"image_url ",[144,3354,265],{"class":257},[144,3356,3357],{"class":257}," f",[144,3359,3360],{"class":158},"\"https://my-bucket.s3.amazonaws.com/seedance/input.jpg\"\n",[144,3362,3363],{"class":146,"line":377},[144,3364,374],{"emptyLinePlaceholder":57},[144,3366,3367],{"class":146,"line":383},[144,3368,3369],{"class":173},"# 方法 2：一時ファイルホスティング API を使用\n",[144,3371,3372],{"class":146,"line":407},[144,3373,3374],{"class":173},"# 多くのサービスがテスト用の無料一時ホスティングを提供しています\n",[10,3376,3377,3378,1768],{},"高度な画像から動画テクニック — 最初/最後のフレーム制御、マルチ画像合成、EC 商品アニメーション — は",[36,3379,3381],{"href":3380},"/blog/seedance-2-image-to-video-api","画像から動画の詳細ガイド",[44,3383],{},[47,3385,3386],{"id":3386},"動画をカスタマイズする",[10,3388,3389],{},"生成リクエストで調整できるすべてのパラメータ：",[2036,3391,3392,3411],{},[2039,3393,3394],{},[2042,3395,3396,3399,3402,3405,3408],{},[2045,3397,3398],{},"パラメータ",[2045,3400,3401],{},"型",[2045,3403,3404],{},"デフォルト",[2045,3406,3407],{},"オプション",[2045,3409,3410],{},"説明",[2052,3412,3413,3432,3448,3465,3488,3520,3542,3559,3576,3592],{},[2042,3414,3415,3419,3422,3425,3429],{},[2057,3416,3417],{},[27,3418,1747],{},[2057,3420,3421],{},"string",[2057,3423,3424],{},"—",[2057,3426,3427],{},[27,3428,1751],{},[2057,3430,3431],{},"必須。使用するモデル。",[2042,3433,3434,3438,3440,3442,3445],{},[2057,3435,3436],{},[27,3437,1762],{},[2057,3439,3421],{},[2057,3441,3424],{},[2057,3443,3444],{},"≤2000 tokens",[2057,3446,3447],{},"必須。@tags を含む動画の説明。",[2042,3449,3450,3454,3457,3459,3462],{},[2057,3451,3452],{},[27,3453,1775],{},[2057,3455,3456],{},"integer",[2057,3458,1352],{},[2057,3460,3461],{},"4–15",[2057,3463,3464],{},"動画の長さ（秒）。",[2042,3466,3467,3471,3473,3477,3485],{},[2057,3468,3469],{},[27,3470,1783],{},[2057,3472,3421],{},[2057,3474,3475],{},[27,3476,1787],{},[2057,3478,3479,2915,3481,2915,3483],{},[27,3480,1791],{},[27,3482,1787],{},[27,3484,1795],{},[2057,3486,3487],{},"解像度ティア。高いほどクレジット消費増。",[2042,3489,3490,3494,3496,3500,3517],{},[2057,3491,3492],{},[27,3493,1803],{},[2057,3495,3421],{},[2057,3497,3498],{},[27,3499,1807],{},[2057,3501,3502,2915,3504,2915,3506,2915,3508,2915,3511,2915,3514],{},[27,3503,1807],{},[27,3505,1811],{},[27,3507,1815],{},[27,3509,3510],{},"4:3",[27,3512,3513],{},"3:4",[27,3515,3516],{},"21:9",[2057,3518,3519],{},"出力アスペクト比。",[2042,3521,3522,3526,3529,3533,3539],{},[2057,3523,3524],{},[27,3525,1823],{},[2057,3527,3528],{},"boolean",[2057,3530,3531],{},[27,3532,1826],{},[2057,3534,3535,2915,3537],{},[27,3536,1826],{},[27,3538,2936],{},[2057,3540,3541],{},"AI 生成オーディオ/音楽を有効化。",[2042,3543,3544,3548,3551,3553,3556],{},[2057,3545,3546],{},[27,3547,2895],{},[2057,3549,3550],{},"array",[2057,3552,3424],{},[2057,3554,3555],{},"≤9 枚",[2057,3557,3558],{},"参照画像。プロンプトで @Image1、@Image2... で参照。",[2042,3560,3561,3566,3568,3570,3573],{},[2057,3562,3563],{},[27,3564,3565],{},"video_urls",[2057,3567,3550],{},[2057,3569,3424],{},[2057,3571,3572],{},"≤3 本",[2057,3574,3575],{},"参照動画。プロンプトで @Video1、@Video2... で参照。",[2042,3577,3578,3583,3585,3587,3589],{},[2057,3579,3580],{},[27,3581,3582],{},"audio_urls",[2057,3584,3550],{},[2057,3586,3424],{},[2057,3588,3572],{},[2057,3590,3591],{},"参照オーディオ。プロンプトで @Audio1、@Audio2... で参照。",[2042,3593,3594,3599,3601,3603,3606],{},[2057,3595,3596],{},[27,3597,3598],{},"callback_url",[2057,3600,3421],{},[2057,3602,3424],{},[2057,3604,3605],{},"HTTPS URL",[2057,3607,3608],{},"完了時の webhook コールバック URL。",[17,3610,3611],{},[10,3612,3613,3616,3617,3619,3620,3622,3623,2915,3625,3627,3628,3630,3631,3633,3634,3637],{},[22,3614,3615],{},"Seedance 2.0 と 1.5 の違い："," 上記のすべてのパラメータは ",[27,3618,1751],{}," と ",[27,3621,29],{}," の両方で動作します。主な違い：",[27,3624,3565],{},[27,3626,3582],{},"、マルチ画像参照（",[27,3629,2918],{},"〜",[27,3632,2955],{},"）は 2.0 専用機能です。1.5 で使用すると、API はその機能がサポートされていないことを明示するメッセージとともに ",[27,3635,3636],{},"400"," エラーを返します。",[91,3639,3640],{"id":3640},"クイック例",[10,3642,3643],{},[22,3644,3645],{},"縦型ソーシャルメディア動画（TikTok/Reels）：",[10,3647,3648],{},[2618,3649,2620],{},[135,3651,3653],{"className":336,"code":3652,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": \"A barista pours latte art in slow motion. Close-up overhead shot.\",\n    \"duration\": 8,\n    \"quality\": \"1080p\",\n    \"aspect_ratio\": \"9:16\",       # モバイル向け縦型\n    \"generate_audio\": True\n}\n",[27,3654,3655,3664,3675,3687,3699,3711,3727,3737],{"__ignoreMap":140},[144,3656,3657,3660,3662],{"class":146,"line":147},[144,3658,3659],{"class":261},"payload ",[144,3661,265],{"class":257},[144,3663,426],{"class":261},[144,3665,3666,3669,3671,3673],{"class":146,"line":165},[144,3667,3668],{"class":158},"    \"model\"",[144,3670,435],{"class":261},[144,3672,1308],{"class":158},[144,3674,450],{"class":261},[144,3676,3677,3680,3682,3685],{"class":146,"line":177},[144,3678,3679],{"class":158},"    \"prompt\"",[144,3681,435],{"class":261},[144,3683,3684],{"class":158},"\"A barista pours latte art in slow motion. Close-up overhead shot.\"",[144,3686,450],{"class":261},[144,3688,3689,3692,3694,3697],{"class":146,"line":186},[144,3690,3691],{"class":158},"    \"duration\"",[144,3693,435],{"class":261},[144,3695,3696],{"class":154},"8",[144,3698,450],{"class":261},[144,3700,3701,3704,3706,3709],{"class":146,"line":371},[144,3702,3703],{"class":158},"    \"quality\"",[144,3705,435],{"class":261},[144,3707,3708],{"class":158},"\"1080p\"",[144,3710,450],{"class":261},[144,3712,3713,3716,3718,3721,3724],{"class":146,"line":377},[144,3714,3715],{"class":158},"    \"aspect_ratio\"",[144,3717,435],{"class":261},[144,3719,3720],{"class":158},"\"9:16\"",[144,3722,3723],{"class":261},",       ",[144,3725,3726],{"class":173},"# モバイル向け縦型\n",[144,3728,3729,3732,3734],{"class":146,"line":383},[144,3730,3731],{"class":158},"    \"generate_audio\"",[144,3733,435],{"class":261},[144,3735,3736],{"class":154},"True\n",[144,3738,3739],{"class":146,"line":407},[144,3740,467],{"class":261},[10,3742,3743,3745,3746,3748],{},[27,3744,1811],{}," アスペクト比は 1080×1920 の動画を生成します — TikTok、Instagram Reels、YouTube Shorts のネイティブ解像度です。",[27,3747,1795],{}," 品質ティアはモバイル画面でも鮮明な映像を実現します。",[10,3750,3751],{},[22,3752,3753],{},"シネマティックワイドスクリーン + カメラムーブメント：",[135,3755,3757],{"className":336,"code":3756,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": (\n        \"Aerial drone shot over a misty mountain range at sunrise. \"\n        \"Camera slowly pushes forward, revealing a hidden valley. \"\n        \"Cinematic color grading, volumetric lighting.\"\n    ),\n    \"duration\": 10,\n    \"quality\": \"1080p\",\n    \"aspect_ratio\": \"21:9\",       # ウルトラワイドスクリーン シネマティック\n    \"generate_audio\": True\n}\n",[27,3758,3759,3767,3777,3783,3788,3793,3798,3803,3813,3823,3837,3845],{"__ignoreMap":140},[144,3760,3761,3763,3765],{"class":146,"line":147},[144,3762,3659],{"class":261},[144,3764,265],{"class":257},[144,3766,426],{"class":261},[144,3768,3769,3771,3773,3775],{"class":146,"line":165},[144,3770,3668],{"class":158},[144,3772,435],{"class":261},[144,3774,1308],{"class":158},[144,3776,450],{"class":261},[144,3778,3779,3781],{"class":146,"line":177},[144,3780,3679],{"class":158},[144,3782,1322],{"class":261},[144,3784,3785],{"class":146,"line":186},[144,3786,3787],{"class":158},"        \"Aerial drone shot over a misty mountain range at sunrise. \"\n",[144,3789,3790],{"class":146,"line":371},[144,3791,3792],{"class":158},"        \"Camera slowly pushes forward, revealing a hidden valley. \"\n",[144,3794,3795],{"class":146,"line":377},[144,3796,3797],{"class":158},"        \"Cinematic color grading, volumetric lighting.\"\n",[144,3799,3800],{"class":146,"line":383},[144,3801,3802],{"class":261},"    ),\n",[144,3804,3805,3807,3809,3811],{"class":146,"line":407},[144,3806,3691],{"class":158},[144,3808,435],{"class":261},[144,3810,535],{"class":154},[144,3812,450],{"class":261},[144,3814,3815,3817,3819,3821],{"class":146,"line":418},[144,3816,3703],{"class":158},[144,3818,435],{"class":261},[144,3820,3708],{"class":158},[144,3822,450],{"class":261},[144,3824,3825,3827,3829,3832,3834],{"class":146,"line":429},[144,3826,3715],{"class":158},[144,3828,435],{"class":261},[144,3830,3831],{"class":158},"\"21:9\"",[144,3833,3723],{"class":261},[144,3835,3836],{"class":173},"# ウルトラワイドスクリーン シネマティック\n",[144,3838,3839,3841,3843],{"class":146,"line":453},[144,3840,3731],{"class":158},[144,3842,435],{"class":261},[144,3844,3736],{"class":154},[144,3846,3847],{"class":146,"line":464},[144,3848,467],{"class":261},[10,3850,3851,3852,1768],{},"プログラムによるカメラ制御 — ドリーズーム、オービタルショット、ヒッチコックスタイルの動き — は",[36,3853,3855],{"href":3854},"/blog/seedance-2-camera-movement-api","カメラムーブメント API ガイド",[10,3857,3858],{},[22,3859,3860],{},"無音ウェブサイト背景動画：",[135,3862,3864],{"className":336,"code":3863,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": \"Abstract flowing particles in deep blue and gold. Slow, meditative movement.\",\n    \"duration\": 15,               # 最大長 — シームレスループ向け\n    \"quality\": \"720p\",\n    \"aspect_ratio\": \"21:9\",       # ワイド背景\n    \"generate_audio\": False       # 自動再生背景にはオーディオ不要\n}\n",[27,3865,3866,3874,3884,3895,3910,3920,3933,3945],{"__ignoreMap":140},[144,3867,3868,3870,3872],{"class":146,"line":147},[144,3869,3659],{"class":261},[144,3871,265],{"class":257},[144,3873,426],{"class":261},[144,3875,3876,3878,3880,3882],{"class":146,"line":165},[144,3877,3668],{"class":158},[144,3879,435],{"class":261},[144,3881,1308],{"class":158},[144,3883,450],{"class":261},[144,3885,3886,3888,3890,3893],{"class":146,"line":177},[144,3887,3679],{"class":158},[144,3889,435],{"class":261},[144,3891,3892],{"class":158},"\"Abstract flowing particles in deep blue and gold. Slow, meditative movement.\"",[144,3894,450],{"class":261},[144,3896,3897,3899,3901,3904,3907],{"class":146,"line":186},[144,3898,3691],{"class":158},[144,3900,435],{"class":261},[144,3902,3903],{"class":154},"15",[144,3905,3906],{"class":261},",               ",[144,3908,3909],{"class":173},"# 最大長 — シームレスループ向け\n",[144,3911,3912,3914,3916,3918],{"class":146,"line":371},[144,3913,3703],{"class":158},[144,3915,435],{"class":261},[144,3917,1368],{"class":158},[144,3919,450],{"class":261},[144,3921,3922,3924,3926,3928,3930],{"class":146,"line":377},[144,3923,3715],{"class":158},[144,3925,435],{"class":261},[144,3927,3831],{"class":158},[144,3929,3723],{"class":261},[144,3931,3932],{"class":173},"# ワイド背景\n",[144,3934,3935,3937,3939,3942],{"class":146,"line":383},[144,3936,3731],{"class":158},[144,3938,435],{"class":261},[144,3940,3941],{"class":154},"False",[144,3943,3944],{"class":173},"       # 自動再生背景にはオーディオ不要\n",[144,3946,3947],{"class":146,"line":407},[144,3948,467],{"class":261},[10,3950,3951],{},[22,3952,3953],{},"低コストドラフト（高速イテレーション）：",[135,3955,3957],{"className":336,"code":3956,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": \"A cat wearing sunglasses sits at a DJ booth. Neon club lighting.\",\n    \"duration\": 4,                # 最短 = 最速生成\n    \"quality\": \"480p\",            # 最低品質 = 最安クレジット\n    \"aspect_ratio\": \"16:9\"\n}\n",[27,3958,3959,3967,3977,3988,4003,4017,4025],{"__ignoreMap":140},[144,3960,3961,3963,3965],{"class":146,"line":147},[144,3962,3659],{"class":261},[144,3964,265],{"class":257},[144,3966,426],{"class":261},[144,3968,3969,3971,3973,3975],{"class":146,"line":165},[144,3970,3668],{"class":158},[144,3972,435],{"class":261},[144,3974,1308],{"class":158},[144,3976,450],{"class":261},[144,3978,3979,3981,3983,3986],{"class":146,"line":177},[144,3980,3679],{"class":158},[144,3982,435],{"class":261},[144,3984,3985],{"class":158},"\"A cat wearing sunglasses sits at a DJ booth. Neon club lighting.\"",[144,3987,450],{"class":261},[144,3989,3990,3992,3994,3997,4000],{"class":146,"line":186},[144,3991,3691],{"class":158},[144,3993,435],{"class":261},[144,3995,3996],{"class":154},"4",[144,3998,3999],{"class":261},",                ",[144,4001,4002],{"class":173},"# 最短 = 最速生成\n",[144,4004,4005,4007,4009,4012,4014],{"class":146,"line":371},[144,4006,3703],{"class":158},[144,4008,435],{"class":261},[144,4010,4011],{"class":158},"\"480p\"",[144,4013,1387],{"class":261},[144,4015,4016],{"class":173},"# 最低品質 = 最安クレジット\n",[144,4018,4019,4021,4023],{"class":146,"line":377},[144,4020,3715],{"class":158},[144,4022,435],{"class":261},[144,4024,2729],{"class":158},[144,4026,4027],{"class":146,"line":383},[144,4028,467],{"class":261},[17,4030,4031],{},[10,4032,4033,4035,4036,3619,4039,4042,4043,4045],{},[22,4034,132],{}," 開発中は常に ",[27,4037,4038],{},"duration: 4",[27,4040,4041],{},"quality: \"480p\""," を使ってください。最も安く最も速い組み合わせで、プロンプトのイテレーションに最適です。内容に満足したら、",[27,4044,1795],{}," と希望の長さで最終版をレンダリングしてください。",[91,4047,4048],{"id":4048},"クレジット消費の目安",[10,4050,4051],{},"クレジットは長さと品質に比例して増加します。大まかな目安：",[2036,4053,4054,4073],{},[2039,4055,4056],{},[2042,4057,4058,4061,4064,4067,4070],{},[2045,4059,4060],{},"品質",[2045,4062,4063],{},"4s",[2045,4065,4066],{},"5s",[2045,4068,4069],{},"10s",[2045,4071,4072],{},"15s",[2052,4074,4075,4091,4107],{},[2042,4076,4077,4079,4082,4085,4088],{},[2057,4078,1791],{},[2057,4080,4081],{},"~8",[2057,4083,4084],{},"~10",[2057,4086,4087],{},"~20",[2057,4089,4090],{},"~30",[2042,4092,4093,4095,4098,4101,4104],{},[2057,4094,1787],{},[2057,4096,4097],{},"~14",[2057,4099,4100],{},"~18",[2057,4102,4103],{},"~36",[2057,4105,4106],{},"~53",[2042,4108,4109,4111,4114,4117,4120],{},[2057,4110,1795],{},[2057,4112,4113],{},"~22",[2057,4115,4116],{},"~28",[2057,4118,4119],{},"~55",[2057,4121,4122],{},"~83",[10,4124,4125],{},[2618,4126,4127,4128,4130,4131,4135],{},"概算クレジット。実際のコストは ",[27,4129,2117],{}," フィールドに表示されます。現在のレートは ",[36,4132,4134],{"href":210,"rel":4133},[40],"EvoLink ダッシュボード","で確認してください。",[10,4137,4138,4139,2915,4142,2915,4144,4146,4147,4150,4151,4154],{},"マルチモーダル参照システム — ",[27,4140,4141],{},"@Image",[27,4143,2959],{},[27,4145,2962],{}," タグ — は Seedance 2.0 の真骨頂です。参照動画から",[36,4148,4149],{"href":3854},"カメラムーブメント","を複製したり、ショット間でキャラクターの一貫性を維持したり、オーディオのビートに同期させたりできます。完全ガイドは ",[36,4152,4153],{"href":2966},"@Tags 究極ガイド","をお読みください。",[44,4156],{},[47,4158,4159],{"id":4159},"エラーを適切に処理する",[10,4161,4162],{},"API コールは失敗します。ネットワークは切断されます。レート制限に引っかかります。実際に起こりうるあらゆるエラーに対応できる堅牢なコードの書き方を解説します。",[91,4164,4165],{"id":4165},"一般的なエラーレスポンス",[10,4167,4168],{},"すべてのエラーは同じフォーマットに従います：",[135,4170,4172],{"className":1856,"code":4171,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"description of what went wrong\",\n    \"type\": \"error_category\",\n    \"code\": \"specific_error_code\"\n  }\n}\n",[27,4173,4174,4178,4185,4197,4209,4219,4223],{"__ignoreMap":140},[144,4175,4176],{"class":146,"line":147},[144,4177,1865],{"class":261},[144,4179,4180,4183],{"class":146,"line":165},[144,4181,4182],{"class":154},"  \"error\"",[144,4184,1943],{"class":261},[144,4186,4187,4190,4192,4195],{"class":146,"line":177},[144,4188,4189],{"class":154},"    \"message\"",[144,4191,435],{"class":261},[144,4193,4194],{"class":158},"\"description of what went wrong\"",[144,4196,450],{"class":261},[144,4198,4199,4202,4204,4207],{"class":146,"line":186},[144,4200,4201],{"class":154},"    \"type\"",[144,4203,435],{"class":261},[144,4205,4206],{"class":158},"\"error_category\"",[144,4208,450],{"class":261},[144,4210,4211,4214,4216],{"class":146,"line":371},[144,4212,4213],{"class":154},"    \"code\"",[144,4215,435],{"class":261},[144,4217,4218],{"class":158},"\"specific_error_code\"\n",[144,4220,4221],{"class":146,"line":377},[144,4222,2027],{"class":261},[144,4224,4225],{"class":146,"line":383},[144,4226,467],{"class":261},[10,4228,4229,4232,4233,3619,4236,4239,4240,4242,4243,4245,4246,4248],{},[27,4230,4231],{},"error"," オブジェクトには常に ",[27,4234,4235],{},"message",[27,4237,4238],{},"type"," が含まれます。",[27,4241,27],{}," フィールドはほとんどのエラーに存在しますが、すべてではありません。まず ",[27,4244,4238],{}," を確認し、詳細は ",[27,4247,27],{}," を確認してください。",[10,4250,4251],{},"API から返される実際のエラーレスポンス：",[10,4253,4254],{},[22,4255,4256],{},"401 — 無効な API Key：",[135,4258,4260],{"className":1856,"code":4259,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"Invalid token (request id: 20260227225245660301729AApJNAhJ)\",\n    \"type\": \"evo_api_error\"\n  }\n}\n",[27,4261,4262,4266,4272,4283,4292,4296],{"__ignoreMap":140},[144,4263,4264],{"class":146,"line":147},[144,4265,1865],{"class":261},[144,4267,4268,4270],{"class":146,"line":165},[144,4269,4182],{"class":154},[144,4271,1943],{"class":261},[144,4273,4274,4276,4278,4281],{"class":146,"line":177},[144,4275,4189],{"class":154},[144,4277,435],{"class":261},[144,4279,4280],{"class":158},"\"Invalid token (request id: 20260227225245660301729AApJNAhJ)\"",[144,4282,450],{"class":261},[144,4284,4285,4287,4289],{"class":146,"line":186},[144,4286,4201],{"class":154},[144,4288,435],{"class":261},[144,4290,4291],{"class":158},"\"evo_api_error\"\n",[144,4293,4294],{"class":146,"line":371},[144,4295,2027],{"class":261},[144,4297,4298],{"class":146,"line":377},[144,4299,467],{"class":261},[10,4301,4302,4303,4305],{},"API Key が間違っている、期限切れ、または取り消されています。",[27,4304,274],{}," 環境変数を再確認してください。よくある原因：Key をコピーする際に末尾の空白が含まれている。",[10,4307,4308],{},[22,4309,4310],{},"400 — 必須フィールドの欠落：",[135,4312,4314],{"className":1856,"code":4313,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"code\": \"invalid_parameter\",\n    \"message\": \"prompt cannot be empty\",\n    \"type\": \"invalid_request_error\"\n  }\n}\n",[27,4315,4316,4320,4326,4337,4348,4357,4361],{"__ignoreMap":140},[144,4317,4318],{"class":146,"line":147},[144,4319,1865],{"class":261},[144,4321,4322,4324],{"class":146,"line":165},[144,4323,4182],{"class":154},[144,4325,1943],{"class":261},[144,4327,4328,4330,4332,4335],{"class":146,"line":177},[144,4329,4213],{"class":154},[144,4331,435],{"class":261},[144,4333,4334],{"class":158},"\"invalid_parameter\"",[144,4336,450],{"class":261},[144,4338,4339,4341,4343,4346],{"class":146,"line":186},[144,4340,4189],{"class":154},[144,4342,435],{"class":261},[144,4344,4345],{"class":158},"\"prompt cannot be empty\"",[144,4347,450],{"class":261},[144,4349,4350,4352,4354],{"class":146,"line":371},[144,4351,4201],{"class":154},[144,4353,435],{"class":261},[144,4355,4356],{"class":158},"\"invalid_request_error\"\n",[144,4358,4359],{"class":146,"line":377},[144,4360,2027],{"class":261},[144,4362,4363],{"class":146,"line":383},[144,4364,467],{"class":261},[10,4366,4367,4369],{},[27,4368,1762],{}," フィールドはすべての生成リクエストで必須です。空文字列やスペースのみのプロンプトでもこのエラーがトリガーされます。",[10,4371,4372],{},[22,4373,4374],{},"400 — 無効なパラメータ値：",[135,4376,4378],{"className":1856,"code":4377,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"code\": \"invalid_parameter\",\n    \"message\": \"duration must be between 4 and 15\",\n    \"type\": \"invalid_request_error\"\n  }\n}\n",[27,4379,4380,4384,4390,4400,4411,4419,4423],{"__ignoreMap":140},[144,4381,4382],{"class":146,"line":147},[144,4383,1865],{"class":261},[144,4385,4386,4388],{"class":146,"line":165},[144,4387,4182],{"class":154},[144,4389,1943],{"class":261},[144,4391,4392,4394,4396,4398],{"class":146,"line":177},[144,4393,4213],{"class":154},[144,4395,435],{"class":261},[144,4397,4334],{"class":158},[144,4399,450],{"class":261},[144,4401,4402,4404,4406,4409],{"class":146,"line":186},[144,4403,4189],{"class":154},[144,4405,435],{"class":261},[144,4407,4408],{"class":158},"\"duration must be between 4 and 15\"",[144,4410,450],{"class":261},[144,4412,4413,4415,4417],{"class":146,"line":371},[144,4414,4201],{"class":154},[144,4416,435],{"class":261},[144,4418,4356],{"class":158},[144,4420,4421],{"class":146,"line":377},[144,4422,2027],{"class":261},[144,4424,4425],{"class":146,"line":383},[144,4426,467],{"class":261},[10,4428,4429,279,4432,4435],{},[27,4430,4431],{},"duration: 3",[27,4433,4434],{},"duration: 20"," を渡した場合に発生します。有効範囲は 4〜15 秒（両端含む）です。",[10,4437,4438],{},[22,4439,4440],{},"402 — クレジット不足：",[135,4442,4444],{"className":1856,"code":4443,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"Insufficient credits. Required: 17.784, Available: 2.100\",\n    \"type\": \"insufficient_quota_error\"\n  }\n}\n",[27,4445,4446,4450,4456,4467,4476,4480],{"__ignoreMap":140},[144,4447,4448],{"class":146,"line":147},[144,4449,1865],{"class":261},[144,4451,4452,4454],{"class":146,"line":165},[144,4453,4182],{"class":154},[144,4455,1943],{"class":261},[144,4457,4458,4460,4462,4465],{"class":146,"line":177},[144,4459,4189],{"class":154},[144,4461,435],{"class":261},[144,4463,4464],{"class":158},"\"Insufficient credits. Required: 17.784, Available: 2.100\"",[144,4466,450],{"class":261},[144,4468,4469,4471,4473],{"class":146,"line":186},[144,4470,4201],{"class":154},[144,4472,435],{"class":261},[144,4474,4475],{"class":158},"\"insufficient_quota_error\"\n",[144,4477,4478],{"class":146,"line":371},[144,4479,2027],{"class":261},[144,4481,4482],{"class":146,"line":377},[144,4483,467],{"class":261},[10,4485,4486,4487,4490],{},"アカウントのクレジットが不足しています。メッセージに必要量と残量が正確に表示されます。",[36,4488,4134],{"href":210,"rel":4489},[40],"でチャージしてください。",[10,4492,4493],{},[22,4494,4495],{},"404 — タスクが見つからない：",[135,4497,4499],{"className":1856,"code":4498,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"Task not found\",\n    \"type\": \"invalid_request_error\",\n    \"code\": \"task_not_found\"\n  }\n}\n",[27,4500,4501,4505,4511,4522,4533,4542,4546],{"__ignoreMap":140},[144,4502,4503],{"class":146,"line":147},[144,4504,1865],{"class":261},[144,4506,4507,4509],{"class":146,"line":165},[144,4508,4182],{"class":154},[144,4510,1943],{"class":261},[144,4512,4513,4515,4517,4520],{"class":146,"line":177},[144,4514,4189],{"class":154},[144,4516,435],{"class":261},[144,4518,4519],{"class":158},"\"Task not found\"",[144,4521,450],{"class":261},[144,4523,4524,4526,4528,4531],{"class":146,"line":186},[144,4525,4201],{"class":154},[144,4527,435],{"class":261},[144,4529,4530],{"class":158},"\"invalid_request_error\"",[144,4532,450],{"class":261},[144,4534,4535,4537,4539],{"class":146,"line":371},[144,4536,4213],{"class":154},[144,4538,435],{"class":261},[144,4540,4541],{"class":158},"\"task_not_found\"\n",[144,4543,4544],{"class":146,"line":377},[144,4545,2027],{"class":261},[144,4547,4548],{"class":146,"line":383},[144,4549,467],{"class":261},[10,4551,4552,4553,4555],{},"通常、タスク ID が間違っているか、タスクが作成から 24 時間以上経過して期限切れになっています。作成レスポンスの ",[27,4554,2061],{}," フィールドを使用しているか確認してください。",[10,4557,4558],{},[22,4559,4560],{},"429 — レート制限：",[135,4562,4564],{"className":1856,"code":4563,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"Rate limit exceeded. Please retry after 60 seconds.\",\n    \"type\": \"rate_limit_error\"\n  }\n}\n",[27,4565,4566,4570,4576,4587,4596,4600],{"__ignoreMap":140},[144,4567,4568],{"class":146,"line":147},[144,4569,1865],{"class":261},[144,4571,4572,4574],{"class":146,"line":165},[144,4573,4182],{"class":154},[144,4575,1943],{"class":261},[144,4577,4578,4580,4582,4585],{"class":146,"line":177},[144,4579,4189],{"class":154},[144,4581,435],{"class":261},[144,4583,4584],{"class":158},"\"Rate limit exceeded. Please retry after 60 seconds.\"",[144,4586,450],{"class":261},[144,4588,4589,4591,4593],{"class":146,"line":186},[144,4590,4201],{"class":154},[144,4592,435],{"class":261},[144,4594,4595],{"class":158},"\"rate_limit_error\"\n",[144,4597,4598],{"class":146,"line":371},[144,4599,2027],{"class":261},[144,4601,4602],{"class":146,"line":377},[144,4603,467],{"class":261},[10,4605,4606],{},"リクエストの送信が頻繁すぎます。デフォルトの制限は開発には十分余裕がありますが、バッチスクリプトでは引っかかる可能性があります。指数バックオフを実装してください（下記参照）。",[10,4608,4609],{},[22,4610,4611],{},"422 — コンテンツ審査による拒否：",[135,4613,4615],{"className":1856,"code":4614,"language":1858,"meta":140,"style":140},"{\n  \"error\": {\n    \"message\": \"Content rejected by safety filter\",\n    \"type\": \"content_policy_violation\",\n    \"code\": \"content_filtered\"\n  }\n}\n",[27,4616,4617,4621,4627,4638,4649,4658,4662],{"__ignoreMap":140},[144,4618,4619],{"class":146,"line":147},[144,4620,1865],{"class":261},[144,4622,4623,4625],{"class":146,"line":165},[144,4624,4182],{"class":154},[144,4626,1943],{"class":261},[144,4628,4629,4631,4633,4636],{"class":146,"line":177},[144,4630,4189],{"class":154},[144,4632,435],{"class":261},[144,4634,4635],{"class":158},"\"Content rejected by safety filter\"",[144,4637,450],{"class":261},[144,4639,4640,4642,4644,4647],{"class":146,"line":186},[144,4641,4201],{"class":154},[144,4643,435],{"class":261},[144,4645,4646],{"class":158},"\"content_policy_violation\"",[144,4648,450],{"class":261},[144,4650,4651,4653,4655],{"class":146,"line":371},[144,4652,4213],{"class":154},[144,4654,435],{"class":261},[144,4656,4657],{"class":158},"\"content_filtered\"\n",[144,4659,4660],{"class":146,"line":377},[144,4661,2027],{"class":261},[144,4663,4664],{"class":146,"line":383},[144,4665,467],{"class":261},[10,4667,4668,4669,4671],{},"プロンプトまたは入力画像がコンテンツ審査システムをトリガーしました。制限されたコンテンツを避けるようプロンプトを修正してください。",[27,4670,2895],{}," のリアルな人物の顔画像は自動的に拒否されます。",[91,4673,4674],{"id":4674},"エラー早見表",[2036,4676,4677,4695],{},[2039,4678,4679],{},[2042,4680,4681,4684,4687,4689,4692],{},[2045,4682,4683],{},"HTTP コード",[2045,4685,4686],{},"タイプ",[2045,4688,2050],{},[2045,4690,4691],{},"リトライ可能？",[2045,4693,4694],{},"対処",[2052,4696,4697,4715,4733,4751,4769,4787,4805,4826,4846,4866],{},[2042,4698,4699,4701,4706,4709,4712],{},[2057,4700,3636],{},[2057,4702,4703],{},[27,4704,4705],{},"invalid_request_error",[2057,4707,4708],{},"パラメータ不正",[2057,4710,4711],{},"いいえ",[2057,4713,4714],{},"payload を修正",[2042,4716,4717,4720,4725,4728,4730],{},[2057,4718,4719],{},"401",[2057,4721,4722],{},[27,4723,4724],{},"authentication_error",[2057,4726,4727],{},"無効な API Key",[2057,4729,4711],{},[2057,4731,4732],{},"Key を確認",[2042,4734,4735,4738,4743,4746,4748],{},[2057,4736,4737],{},"402",[2057,4739,4740],{},[27,4741,4742],{},"insufficient_quota_error",[2057,4744,4745],{},"クレジット不足",[2057,4747,4711],{},[2057,4749,4750],{},"チャージ",[2042,4752,4753,4756,4761,4764,4766],{},[2057,4754,4755],{},"404",[2057,4757,4758],{},[27,4759,4760],{},"not_found_error",[2057,4762,4763],{},"タスクまたはモデルが見つからない",[2057,4765,4711],{},[2057,4767,4768],{},"task_id / モデル名を確認",[2042,4770,4771,4774,4779,4782,4784],{},[2057,4772,4773],{},"413",[2057,4775,4776],{},[27,4777,4778],{},"request_too_large_error",[2057,4780,4781],{},"リクエストが大きすぎる",[2057,4783,4711],{},[2057,4785,4786],{},"ファイルサイズを削減",[2042,4788,4789,4792,4797,4800,4802],{},[2057,4790,4791],{},"422",[2057,4793,4794],{},[27,4795,4796],{},"content_policy_violation",[2057,4798,4799],{},"コンテンツがフィルタリングされた",[2057,4801,4711],{},[2057,4803,4804],{},"プロンプトを修正",[2042,4806,4807,4810,4815,4818,4823],{},[2057,4808,4809],{},"429",[2057,4811,4812],{},[27,4813,4814],{},"rate_limit_error",[2057,4816,4817],{},"リクエストが頻繁すぎる",[2057,4819,4820],{},[22,4821,4822],{},"はい",[2057,4824,4825],{},"60 秒後にリトライ",[2042,4827,4828,4831,4836,4839,4843],{},[2057,4829,4830],{},"500",[2057,4832,4833],{},[27,4834,4835],{},"internal_server_error",[2057,4837,4838],{},"サーバー問題",[2057,4840,4841],{},[22,4842,4822],{},[2057,4844,4845],{},"数秒後にリトライ",[2042,4847,4848,4851,4856,4859,4863],{},[2057,4849,4850],{},"502",[2057,4852,4853],{},[27,4854,4855],{},"bad_gateway",[2057,4857,4858],{},"アップストリームエラー",[2057,4860,4861],{},[22,4862,4822],{},[2057,4864,4865],{},"5 秒後にリトライ",[2042,4867,4868,4871,4876,4879,4883],{},[2057,4869,4870],{},"503",[2057,4872,4873],{},[27,4874,4875],{},"service_unavailable_error",[2057,4877,4878],{},"サービス利用不可",[2057,4880,4881],{},[22,4882,4822],{},[2057,4884,4885],{},"30 秒後にリトライ",[91,4887,4888],{"id":4888},"プロダクション品質のエラー処理",[10,4890,4891],{},"一時的なエラーに対するリトライロジックで API コールをラップします：",[10,4893,4894],{},[2618,4895,2620],{},[135,4897,4899],{"className":336,"code":4898,"language":338,"meta":140,"style":140},"import random\n\ndef generate_video_with_retry(payload, max_retries=3):\n    \"\"\"\n    一時的なエラー（429、500、502、503）に対して自動リトライする\n    動画生成リクエストの送信。\n    \n    Thundering Herd 問題を避けるため指数バックオフ + ジッターを使用：\n    - 試行 1：〜1 秒待機\n    - 試行 2：〜2 秒待機\n    - 試行 3：〜4 秒待機\n    \n    リトライ不可能なエラー（400、401、402、404、413、422）は\n    根本的な問題をリトライで解決できないため即座に失敗します。\n    \"\"\"\n    for attempt in range(max_retries):\n        try:\n            response = requests.post(\n                f\"{BASE_URL}/videos/generations\",\n                headers=HEADERS,\n                json=payload,\n                timeout=30       # 30 秒接続タイムアウト\n            )\n\n            # 成功 — task オブジェクトを返す\n            if response.status_code == 200:\n                return response.json()\n\n            # エラーレスポンスをパース\n            error = response.json().get(\"error\", {})\n            error_type = error.get(\"type\", \"\")\n            error_msg = error.get(\"message\", \"Unknown error\")\n\n            # リトライ不可能なエラー — 即座に失敗\n            if response.status_code in (400, 401, 402, 404, 413, 422):\n                raise ValueError(\n                    f\"API error {response.status_code}: {error_msg}\"\n                )\n\n            # リトライ可能なエラー — 指数バックオフ + ジッター\n            if response.status_code in (429, 500, 502, 503):\n                wait = (2 ** attempt) + random.uniform(0, 1)\n                print(f\"  Retry {attempt + 1}/{max_retries} \"\n                      f\"after {wait:.1f}s ({error_type}: {error_msg})\")\n                time.sleep(wait)\n                continue\n\n        except requests.exceptions.Timeout:\n            wait = (2 ** attempt) + random.uniform(0, 1)\n            print(f\"  Timeout. Retry {attempt + 1}/{max_retries} \"\n                  f\"after {wait:.1f}s\")\n            time.sleep(wait)\n            continue\n\n        except requests.exceptions.ConnectionError as e:\n            wait = (2 ** attempt) + random.uniform(0, 1)\n            print(f\"  Connection error: {e}. Retry {attempt + 1}/{max_retries} \"\n                  f\"after {wait:.1f}s\")\n            time.sleep(wait)\n            continue\n\n    raise RuntimeError(f\"Failed after {max_retries} retries\")\n",[27,4900,4901,4908,4912,4929,4933,4938,4943,4947,4952,4957,4962,4967,4971,4976,4981,4985,5001,5008,5017,5029,5040,5050,5063,5067,5071,5076,5089,5096,5100,5105,5119,5139,5158,5162,5167,5201,5211,5237,5242,5246,5251,5277,5310,5344,5385,5390,5395,5399,5408,5436,5467,5487,5493,5499,5504,5517,5544,5584,5603,5608,5613,5618],{"__ignoreMap":140},[144,4902,4903,4905],{"class":146,"line":147},[144,4904,345],{"class":257},[144,4906,4907],{"class":261}," random\n",[144,4909,4910],{"class":146,"line":165},[144,4911,374],{"emptyLinePlaceholder":57},[144,4913,4914,4916,4919,4922,4924,4927],{"class":146,"line":177},[144,4915,524],{"class":257},[144,4917,4918],{"class":150}," generate_video_with_retry",[144,4920,4921],{"class":261},"(payload, max_retries",[144,4923,265],{"class":257},[144,4925,4926],{"class":154},"3",[144,4928,546],{"class":261},[144,4930,4931],{"class":146,"line":186},[144,4932,551],{"class":158},[144,4934,4935],{"class":146,"line":371},[144,4936,4937],{"class":158},"    一時的なエラー（429、500、502、503）に対して自動リトライする\n",[144,4939,4940],{"class":146,"line":377},[144,4941,4942],{"class":158},"    動画生成リクエストの送信。\n",[144,4944,4945],{"class":146,"line":383},[144,4946,561],{"class":158},[144,4948,4949],{"class":146,"line":407},[144,4950,4951],{"class":158},"    Thundering Herd 問題を避けるため指数バックオフ + ジッターを使用：\n",[144,4953,4954],{"class":146,"line":418},[144,4955,4956],{"class":158},"    - 試行 1：〜1 秒待機\n",[144,4958,4959],{"class":146,"line":429},[144,4960,4961],{"class":158},"    - 試行 2：〜2 秒待機\n",[144,4963,4964],{"class":146,"line":453},[144,4965,4966],{"class":158},"    - 試行 3：〜4 秒待機\n",[144,4968,4969],{"class":146,"line":464},[144,4970,561],{"class":158},[144,4972,4973],{"class":146,"line":598},[144,4974,4975],{"class":158},"    リトライ不可能なエラー（400、401、402、404、413、422）は\n",[144,4977,4978],{"class":146,"line":603},[144,4979,4980],{"class":158},"    根本的な問題をリトライで解決できないため即座に失敗します。\n",[144,4982,4983],{"class":146,"line":609},[144,4984,551],{"class":158},[144,4986,4987,4990,4993,4995,4998],{"class":146,"line":615},[144,4988,4989],{"class":257},"    for",[144,4991,4992],{"class":261}," attempt ",[144,4994,1179],{"class":257},[144,4996,4997],{"class":154}," range",[144,4999,5000],{"class":261},"(max_retries):\n",[144,5002,5003,5006],{"class":146,"line":621},[144,5004,5005],{"class":257},"        try",[144,5007,858],{"class":261},[144,5009,5010,5013,5015],{"class":146,"line":626},[144,5011,5012],{"class":261},"            response ",[144,5014,265],{"class":257},[144,5016,1432],{"class":261},[144,5018,5019,5021,5023,5025,5027],{"class":146,"line":637},[144,5020,916],{"class":257},[144,5022,447],{"class":158},[144,5024,677],{"class":154},[144,5026,1444],{"class":158},[144,5028,450],{"class":261},[144,5030,5031,5034,5036,5038],{"class":146,"line":652},[144,5032,5033],{"class":699},"                headers",[144,5035,265],{"class":257},[144,5037,421],{"class":154},[144,5039,450],{"class":261},[144,5041,5042,5045,5047],{"class":146,"line":658},[144,5043,5044],{"class":699},"                json",[144,5046,265],{"class":257},[144,5048,5049],{"class":261},"payload,\n",[144,5051,5052,5055,5057,5060],{"class":146,"line":669},[144,5053,5054],{"class":699},"                timeout",[144,5056,265],{"class":257},[144,5058,5059],{"class":154},"30",[144,5061,5062],{"class":173},"       # 30 秒接続タイムアウト\n",[144,5064,5065],{"class":146,"line":696},[144,5066,955],{"class":261},[144,5068,5069],{"class":146,"line":708},[144,5070,374],{"emptyLinePlaceholder":57},[144,5072,5073],{"class":146,"line":714},[144,5074,5075],{"class":173},"            # 成功 — task オブジェクトを返す\n",[144,5077,5078,5081,5083,5085,5087],{"class":146,"line":720},[144,5079,5080],{"class":257},"            if",[144,5082,2507],{"class":261},[144,5084,852],{"class":257},[144,5086,2512],{"class":154},[144,5088,858],{"class":261},[144,5090,5091,5094],{"class":146,"line":726},[144,5092,5093],{"class":257},"                return",[144,5095,734],{"class":261},[144,5097,5098],{"class":146,"line":737},[144,5099,374],{"emptyLinePlaceholder":57},[144,5101,5102],{"class":146,"line":742},[144,5103,5104],{"class":173},"            # エラーレスポンスをパース\n",[144,5106,5107,5110,5112,5115,5117],{"class":146,"line":748},[144,5108,5109],{"class":261},"            error ",[144,5111,265],{"class":257},[144,5113,5114],{"class":261}," response.json().get(",[144,5116,895],{"class":158},[144,5118,898],{"class":261},[144,5120,5121,5124,5126,5129,5132,5134,5137],{"class":146,"line":765},[144,5122,5123],{"class":261},"            error_type ",[144,5125,265],{"class":257},[144,5127,5128],{"class":261}," error.get(",[144,5130,5131],{"class":158},"\"type\"",[144,5133,398],{"class":261},[144,5135,5136],{"class":158},"\"\"",[144,5138,404],{"class":261},[144,5140,5141,5144,5146,5148,5151,5153,5156],{"class":146,"line":786},[144,5142,5143],{"class":261},"            error_msg ",[144,5145,265],{"class":257},[144,5147,5128],{"class":261},[144,5149,5150],{"class":158},"\"message\"",[144,5152,398],{"class":261},[144,5154,5155],{"class":158},"\"Unknown error\"",[144,5157,404],{"class":261},[144,5159,5160],{"class":146,"line":832},[144,5161,374],{"emptyLinePlaceholder":57},[144,5163,5164],{"class":146,"line":837},[144,5165,5166],{"class":173},"            # リトライ不可能なエラー — 即座に失敗\n",[144,5168,5169,5171,5173,5175,5177,5179,5181,5183,5185,5187,5189,5191,5193,5195,5197,5199],{"class":146,"line":843},[144,5170,5080],{"class":257},[144,5172,2507],{"class":261},[144,5174,1179],{"class":257},[144,5176,1217],{"class":261},[144,5178,3636],{"class":154},[144,5180,398],{"class":261},[144,5182,4719],{"class":154},[144,5184,398],{"class":261},[144,5186,4737],{"class":154},[144,5188,398],{"class":261},[144,5190,4755],{"class":154},[144,5192,398],{"class":261},[144,5194,4773],{"class":154},[144,5196,398],{"class":261},[144,5198,4791],{"class":154},[144,5200,546],{"class":261},[144,5202,5203,5206,5209],{"class":146,"line":861},[144,5204,5205],{"class":257},"                raise",[144,5207,5208],{"class":154}," ValueError",[144,5210,910],{"class":261},[144,5212,5213,5216,5219,5221,5224,5226,5228,5230,5233,5235],{"class":146,"line":870},[144,5214,5215],{"class":257},"                    f",[144,5217,5218],{"class":158},"\"API error ",[144,5220,683],{"class":154},[144,5222,5223],{"class":261},"response.status_code",[144,5225,689],{"class":154},[144,5227,435],{"class":158},[144,5229,683],{"class":154},[144,5231,5232],{"class":261},"error_msg",[144,5234,689],{"class":154},[144,5236,949],{"class":158},[144,5238,5239],{"class":146,"line":885},[144,5240,5241],{"class":261},"                )\n",[144,5243,5244],{"class":146,"line":901},[144,5245,374],{"emptyLinePlaceholder":57},[144,5247,5248],{"class":146,"line":913},[144,5249,5250],{"class":173},"            # リトライ可能なエラー — 指数バックオフ + ジッター\n",[144,5252,5253,5255,5257,5259,5261,5263,5265,5267,5269,5271,5273,5275],{"class":146,"line":952},[144,5254,5080],{"class":257},[144,5256,2507],{"class":261},[144,5258,1179],{"class":257},[144,5260,1217],{"class":261},[144,5262,4809],{"class":154},[144,5264,398],{"class":261},[144,5266,4830],{"class":154},[144,5268,398],{"class":261},[144,5270,4850],{"class":154},[144,5272,398],{"class":261},[144,5274,4870],{"class":154},[144,5276,546],{"class":261},[144,5278,5279,5282,5284,5286,5289,5292,5295,5298,5301,5303,5305,5308],{"class":146,"line":958},[144,5280,5281],{"class":261},"                wait ",[144,5283,265],{"class":257},[144,5285,1217],{"class":261},[144,5287,5288],{"class":154},"2",[144,5290,5291],{"class":257}," **",[144,5293,5294],{"class":261}," attempt) ",[144,5296,5297],{"class":257},"+",[144,5299,5300],{"class":261}," random.uniform(",[144,5302,781],{"class":154},[144,5304,398],{"class":261},[144,5306,5307],{"class":154},"1",[144,5309,404],{"class":261},[144,5311,5312,5315,5317,5319,5322,5324,5327,5329,5332,5334,5336,5339,5341],{"class":146,"line":963},[144,5313,5314],{"class":154},"                print",[144,5316,792],{"class":261},[144,5318,438],{"class":257},[144,5320,5321],{"class":158},"\"  Retry ",[144,5323,683],{"class":154},[144,5325,5326],{"class":261},"attempt ",[144,5328,5297],{"class":257},[144,5330,5331],{"class":154}," 1}",[144,5333,1225],{"class":158},[144,5335,683],{"class":154},[144,5337,5338],{"class":261},"max_retries",[144,5340,689],{"class":154},[144,5342,5343],{"class":158}," \"\n",[144,5345,5346,5349,5352,5354,5357,5360,5362,5365,5367,5370,5372,5374,5376,5378,5380,5383],{"class":146,"line":969},[144,5347,5348],{"class":257},"                      f",[144,5350,5351],{"class":158},"\"after ",[144,5353,683],{"class":154},[144,5355,5356],{"class":261},"wait",[144,5358,5359],{"class":257},":.1f",[144,5361,689],{"class":154},[144,5363,5364],{"class":158},"s (",[144,5366,683],{"class":154},[144,5368,5369],{"class":261},"error_type",[144,5371,689],{"class":154},[144,5373,435],{"class":158},[144,5375,683],{"class":154},[144,5377,5232],{"class":261},[144,5379,689],{"class":154},[144,5381,5382],{"class":158},")\"",[144,5384,404],{"class":261},[144,5386,5387],{"class":146,"line":975},[144,5388,5389],{"class":261},"                time.sleep(wait)\n",[144,5391,5392],{"class":146,"line":987},[144,5393,5394],{"class":257},"                continue\n",[144,5396,5397],{"class":146,"line":992},[144,5398,374],{"emptyLinePlaceholder":57},[144,5400,5402,5405],{"class":146,"line":5401},48,[144,5403,5404],{"class":257},"        except",[144,5406,5407],{"class":261}," requests.exceptions.Timeout:\n",[144,5409,5411,5414,5416,5418,5420,5422,5424,5426,5428,5430,5432,5434],{"class":146,"line":5410},49,[144,5412,5413],{"class":261},"            wait ",[144,5415,265],{"class":257},[144,5417,1217],{"class":261},[144,5419,5288],{"class":154},[144,5421,5291],{"class":257},[144,5423,5294],{"class":261},[144,5425,5297],{"class":257},[144,5427,5300],{"class":261},[144,5429,781],{"class":154},[144,5431,398],{"class":261},[144,5433,5307],{"class":154},[144,5435,404],{"class":261},[144,5437,5439,5442,5444,5446,5449,5451,5453,5455,5457,5459,5461,5463,5465],{"class":146,"line":5438},50,[144,5440,5441],{"class":154},"            print",[144,5443,792],{"class":261},[144,5445,438],{"class":257},[144,5447,5448],{"class":158},"\"  Timeout. Retry ",[144,5450,683],{"class":154},[144,5452,5326],{"class":261},[144,5454,5297],{"class":257},[144,5456,5331],{"class":154},[144,5458,1225],{"class":158},[144,5460,683],{"class":154},[144,5462,5338],{"class":261},[144,5464,689],{"class":154},[144,5466,5343],{"class":158},[144,5468,5470,5473,5475,5477,5479,5481,5483,5485],{"class":146,"line":5469},51,[144,5471,5472],{"class":257},"                  f",[144,5474,5351],{"class":158},[144,5476,683],{"class":154},[144,5478,5356],{"class":261},[144,5480,5359],{"class":257},[144,5482,689],{"class":154},[144,5484,1023],{"class":158},[144,5486,404],{"class":261},[144,5488,5490],{"class":146,"line":5489},52,[144,5491,5492],{"class":261},"            time.sleep(wait)\n",[144,5494,5496],{"class":146,"line":5495},53,[144,5497,5498],{"class":257},"            continue\n",[144,5500,5502],{"class":146,"line":5501},54,[144,5503,374],{"emptyLinePlaceholder":57},[144,5505,5507,5509,5512,5514],{"class":146,"line":5506},55,[144,5508,5404],{"class":257},[144,5510,5511],{"class":261}," requests.exceptions.ConnectionError ",[144,5513,1165],{"class":257},[144,5515,5516],{"class":261}," e:\n",[144,5518,5520,5522,5524,5526,5528,5530,5532,5534,5536,5538,5540,5542],{"class":146,"line":5519},56,[144,5521,5413],{"class":261},[144,5523,265],{"class":257},[144,5525,1217],{"class":261},[144,5527,5288],{"class":154},[144,5529,5291],{"class":257},[144,5531,5294],{"class":261},[144,5533,5297],{"class":257},[144,5535,5300],{"class":261},[144,5537,781],{"class":154},[144,5539,398],{"class":261},[144,5541,5307],{"class":154},[144,5543,404],{"class":261},[144,5545,5547,5549,5551,5553,5556,5558,5561,5563,5566,5568,5570,5572,5574,5576,5578,5580,5582],{"class":146,"line":5546},57,[144,5548,5441],{"class":154},[144,5550,792],{"class":261},[144,5552,438],{"class":257},[144,5554,5555],{"class":158},"\"  Connection error: ",[144,5557,683],{"class":154},[144,5559,5560],{"class":261},"e",[144,5562,689],{"class":154},[144,5564,5565],{"class":158},". Retry ",[144,5567,683],{"class":154},[144,5569,5326],{"class":261},[144,5571,5297],{"class":257},[144,5573,5331],{"class":154},[144,5575,1225],{"class":158},[144,5577,683],{"class":154},[144,5579,5338],{"class":261},[144,5581,689],{"class":154},[144,5583,5343],{"class":158},[144,5585,5587,5589,5591,5593,5595,5597,5599,5601],{"class":146,"line":5586},58,[144,5588,5472],{"class":257},[144,5590,5351],{"class":158},[144,5592,683],{"class":154},[144,5594,5356],{"class":261},[144,5596,5359],{"class":257},[144,5598,689],{"class":154},[144,5600,1023],{"class":158},[144,5602,404],{"class":261},[144,5604,5606],{"class":146,"line":5605},59,[144,5607,5492],{"class":261},[144,5609,5611],{"class":146,"line":5610},60,[144,5612,5498],{"class":257},[144,5614,5616],{"class":146,"line":5615},61,[144,5617,374],{"emptyLinePlaceholder":57},[144,5619,5621,5623,5625,5627,5629,5632,5634,5636,5638,5641],{"class":146,"line":5620},62,[144,5622,995],{"class":257},[144,5624,907],{"class":154},[144,5626,792],{"class":261},[144,5628,438],{"class":257},[144,5630,5631],{"class":158},"\"Failed after ",[144,5633,683],{"class":154},[144,5635,5338],{"class":261},[144,5637,689],{"class":154},[144,5639,5640],{"class":158}," retries\"",[144,5642,404],{"class":261},[10,5644,5645],{},"このコードが処理するもの：",[95,5647,5648,5654,5660,5666,5672],{},[72,5649,5650,5653],{},[22,5651,5652],{},"レート制限（429）"," — 指数バックオフ + ジッターで複数クライアントの同期リトライを防止",[72,5655,5656,5659],{},[22,5657,5658],{},"サーバーエラー（500/502/503）"," — 増加する遅延で自動リトライ",[72,5661,5662,5665],{},[22,5663,5664],{},"タイムアウト"," — 30 秒タイムアウトで応答のないサーバーでのハングを防止",[72,5667,5668,5671],{},[22,5669,5670],{},"接続切断"," — DNS 解決失敗、接続拒否、ネットワークの瞬断",[72,5673,5674,5677],{},[22,5675,5676],{},"クライアントエラー（400/401/402/404/413/422）"," — 即座に失敗（リトライしても不正な入力は修正されない）",[17,5679,5680],{},[10,5681,5682,5684],{},[22,5683,132],{}," プロダクションシステムでは、失敗したリクエストの完全な payload とエラーレスポンスをログに記録することをお勧めします。深夜 3 時に問題が発生したとき、デバッグがはるかに楽になります。",[91,5686,5688],{"id":5687},"api-コール前の入力バリデーション","API コール前の入力バリデーション",[10,5690,5691],{},"API リクエストを送信する前にローカルで明らかなエラーをキャッチし、クレジットと時間を節約します：",[135,5693,5695],{"className":336,"code":5694,"language":338,"meta":140,"style":140},"def validate_payload(payload):\n    \"\"\"\n    API に送信する前に生成 payload をバリデーションします。\n    400 エラーになるよくある間違いをキャッチします。\n    \"\"\"\n    errors = []\n    \n    # 必須フィールド\n    if not payload.get(\"model\"):\n        errors.append(\"'model' is required\")\n    if not payload.get(\"prompt\") or not payload[\"prompt\"].strip():\n        errors.append(\"'prompt' is required and cannot be empty\")\n    \n    # duration の範囲\n    duration = payload.get(\"duration\", 5)\n    if duration \u003C 4 or duration > 15:\n        errors.append(f\"'duration' must be 4-15, got {duration}\")\n    \n    # quality の値\n    valid_qualities = {\"480p\", \"720p\", \"1080p\"}\n    quality = payload.get(\"quality\", \"720p\")\n    if quality not in valid_qualities:\n        errors.append(f\"'quality' must be one of {valid_qualities}, got '{quality}'\")\n    \n    # aspect_ratio の値\n    valid_ratios = {\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\", \"21:9\"}\n    ratio = payload.get(\"aspect_ratio\", \"16:9\")\n    if ratio not in valid_ratios:\n        errors.append(f\"'aspect_ratio' must be one of {valid_ratios}, got '{ratio}'\")\n    \n    # 画像 URL のバリデーション\n    image_urls = payload.get(\"image_urls\", [])\n    if len(image_urls) > 9:\n        errors.append(f\"Maximum 9 images allowed, got {len(image_urls)}\")\n    for i, url in enumerate(image_urls):\n        if not url.startswith((\"http://\", \"https://\")):\n            errors.append(f\"image_urls[{i}] must be an HTTP(S) URL\")\n    \n    if errors:\n        raise ValueError(f\"Payload validation failed:\\n\" + \"\\n\".join(f\"  - {e}\" for e in errors))\n    \n    return True\n",[27,5696,5697,5707,5711,5716,5721,5725,5735,5739,5744,5759,5769,5795,5804,5808,5813,5831,5856,5875,5879,5884,5906,5924,5940,5970,5974,5979,6015,6033,6047,6076,6080,6085,6100,6117,6138,6153,6173,6195,6199,6206,6261,6265],{"__ignoreMap":140},[144,5698,5699,5701,5704],{"class":146,"line":147},[144,5700,524],{"class":257},[144,5702,5703],{"class":150}," validate_payload",[144,5705,5706],{"class":261},"(payload):\n",[144,5708,5709],{"class":146,"line":165},[144,5710,551],{"class":158},[144,5712,5713],{"class":146,"line":177},[144,5714,5715],{"class":158},"    API に送信する前に生成 payload をバリデーションします。\n",[144,5717,5718],{"class":146,"line":186},[144,5719,5720],{"class":158},"    400 エラーになるよくある間違いをキャッチします。\n",[144,5722,5723],{"class":146,"line":371},[144,5724,551],{"class":158},[144,5726,5727,5730,5732],{"class":146,"line":377},[144,5728,5729],{"class":261},"    errors ",[144,5731,265],{"class":257},[144,5733,5734],{"class":261}," []\n",[144,5736,5737],{"class":146,"line":383},[144,5738,561],{"class":261},[144,5740,5741],{"class":146,"line":407},[144,5742,5743],{"class":173},"    # 必須フィールド\n",[144,5745,5746,5748,5751,5754,5757],{"class":146,"line":418},[144,5747,2504],{"class":257},[144,5749,5750],{"class":257}," not",[144,5752,5753],{"class":261}," payload.get(",[144,5755,5756],{"class":158},"\"model\"",[144,5758,546],{"class":261},[144,5760,5761,5764,5767],{"class":146,"line":429},[144,5762,5763],{"class":261},"        errors.append(",[144,5765,5766],{"class":158},"\"'model' is required\"",[144,5768,404],{"class":261},[144,5770,5771,5773,5775,5777,5780,5782,5785,5787,5790,5792],{"class":146,"line":453},[144,5772,2504],{"class":257},[144,5774,5750],{"class":257},[144,5776,5753],{"class":261},[144,5778,5779],{"class":158},"\"prompt\"",[144,5781,1162],{"class":261},[144,5783,5784],{"class":257},"or",[144,5786,5750],{"class":257},[144,5788,5789],{"class":261}," payload[",[144,5791,5779],{"class":158},[144,5793,5794],{"class":261},"].strip():\n",[144,5796,5797,5799,5802],{"class":146,"line":464},[144,5798,5763],{"class":261},[144,5800,5801],{"class":158},"\"'prompt' is required and cannot be empty\"",[144,5803,404],{"class":261},[144,5805,5806],{"class":146,"line":598},[144,5807,561],{"class":261},[144,5809,5810],{"class":146,"line":603},[144,5811,5812],{"class":173},"    # duration の範囲\n",[144,5814,5815,5818,5820,5822,5825,5827,5829],{"class":146,"line":609},[144,5816,5817],{"class":261},"    duration ",[144,5819,265],{"class":257},[144,5821,5753],{"class":261},[144,5823,5824],{"class":158},"\"duration\"",[144,5826,398],{"class":261},[144,5828,1352],{"class":154},[144,5830,404],{"class":261},[144,5832,5833,5835,5838,5840,5843,5846,5848,5851,5854],{"class":146,"line":615},[144,5834,2504],{"class":257},[144,5836,5837],{"class":261}," duration ",[144,5839,646],{"class":257},[144,5841,5842],{"class":154}," 4",[144,5844,5845],{"class":257}," or",[144,5847,5837],{"class":261},[144,5849,5850],{"class":257},">",[144,5852,5853],{"class":154}," 15",[144,5855,858],{"class":261},[144,5857,5858,5860,5862,5865,5867,5869,5871,5873],{"class":146,"line":621},[144,5859,5763],{"class":261},[144,5861,438],{"class":257},[144,5863,5864],{"class":158},"\"'duration' must be 4-15, got ",[144,5866,683],{"class":154},[144,5868,1775],{"class":261},[144,5870,689],{"class":154},[144,5872,447],{"class":158},[144,5874,404],{"class":261},[144,5876,5877],{"class":146,"line":626},[144,5878,561],{"class":261},[144,5880,5881],{"class":146,"line":637},[144,5882,5883],{"class":173},"    # quality の値\n",[144,5885,5886,5889,5891,5894,5896,5898,5900,5902,5904],{"class":146,"line":652},[144,5887,5888],{"class":261},"    valid_qualities ",[144,5890,265],{"class":257},[144,5892,5893],{"class":261}," {",[144,5895,4011],{"class":158},[144,5897,398],{"class":261},[144,5899,1368],{"class":158},[144,5901,398],{"class":261},[144,5903,3708],{"class":158},[144,5905,467],{"class":261},[144,5907,5908,5911,5913,5915,5918,5920,5922],{"class":146,"line":658},[144,5909,5910],{"class":261},"    quality ",[144,5912,265],{"class":257},[144,5914,5753],{"class":261},[144,5916,5917],{"class":158},"\"quality\"",[144,5919,398],{"class":261},[144,5921,1368],{"class":158},[144,5923,404],{"class":261},[144,5925,5926,5928,5931,5934,5937],{"class":146,"line":669},[144,5927,2504],{"class":257},[144,5929,5930],{"class":261}," quality ",[144,5932,5933],{"class":257},"not",[144,5935,5936],{"class":257}," in",[144,5938,5939],{"class":261}," valid_qualities:\n",[144,5941,5942,5944,5946,5949,5951,5954,5956,5959,5961,5963,5965,5968],{"class":146,"line":696},[144,5943,5763],{"class":261},[144,5945,438],{"class":257},[144,5947,5948],{"class":158},"\"'quality' must be one of ",[144,5950,683],{"class":154},[144,5952,5953],{"class":261},"valid_qualities",[144,5955,689],{"class":154},[144,5957,5958],{"class":158},", got '",[144,5960,683],{"class":154},[144,5962,1783],{"class":261},[144,5964,689],{"class":154},[144,5966,5967],{"class":158},"'\"",[144,5969,404],{"class":261},[144,5971,5972],{"class":146,"line":708},[144,5973,561],{"class":261},[144,5975,5976],{"class":146,"line":714},[144,5977,5978],{"class":173},"    # aspect_ratio の値\n",[144,5980,5981,5984,5986,5988,5990,5992,5994,5996,5999,6001,6004,6006,6009,6011,6013],{"class":146,"line":720},[144,5982,5983],{"class":261},"    valid_ratios ",[144,5985,265],{"class":257},[144,5987,5893],{"class":261},[144,5989,1384],{"class":158},[144,5991,398],{"class":261},[144,5993,3720],{"class":158},[144,5995,398],{"class":261},[144,5997,5998],{"class":158},"\"1:1\"",[144,6000,398],{"class":261},[144,6002,6003],{"class":158},"\"4:3\"",[144,6005,398],{"class":261},[144,6007,6008],{"class":158},"\"3:4\"",[144,6010,398],{"class":261},[144,6012,3831],{"class":158},[144,6014,467],{"class":261},[144,6016,6017,6020,6022,6024,6027,6029,6031],{"class":146,"line":726},[144,6018,6019],{"class":261},"    ratio ",[144,6021,265],{"class":257},[144,6023,5753],{"class":261},[144,6025,6026],{"class":158},"\"aspect_ratio\"",[144,6028,398],{"class":261},[144,6030,1384],{"class":158},[144,6032,404],{"class":261},[144,6034,6035,6037,6040,6042,6044],{"class":146,"line":737},[144,6036,2504],{"class":257},[144,6038,6039],{"class":261}," ratio ",[144,6041,5933],{"class":257},[144,6043,5936],{"class":257},[144,6045,6046],{"class":261}," valid_ratios:\n",[144,6048,6049,6051,6053,6056,6058,6061,6063,6065,6067,6070,6072,6074],{"class":146,"line":742},[144,6050,5763],{"class":261},[144,6052,438],{"class":257},[144,6054,6055],{"class":158},"\"'aspect_ratio' must be one of ",[144,6057,683],{"class":154},[144,6059,6060],{"class":261},"valid_ratios",[144,6062,689],{"class":154},[144,6064,5958],{"class":158},[144,6066,683],{"class":154},[144,6068,6069],{"class":261},"ratio",[144,6071,689],{"class":154},[144,6073,5967],{"class":158},[144,6075,404],{"class":261},[144,6077,6078],{"class":146,"line":748},[144,6079,561],{"class":261},[144,6081,6082],{"class":146,"line":765},[144,6083,6084],{"class":173},"    # 画像 URL のバリデーション\n",[144,6086,6087,6090,6092,6094,6097],{"class":146,"line":786},[144,6088,6089],{"class":261},"    image_urls ",[144,6091,265],{"class":257},[144,6093,5753],{"class":261},[144,6095,6096],{"class":158},"\"image_urls\"",[144,6098,6099],{"class":261},", [])\n",[144,6101,6102,6104,6107,6110,6112,6115],{"class":146,"line":832},[144,6103,2504],{"class":257},[144,6105,6106],{"class":154}," len",[144,6108,6109],{"class":261},"(image_urls) ",[144,6111,5850],{"class":257},[144,6113,6114],{"class":154}," 9",[144,6116,858],{"class":261},[144,6118,6119,6121,6123,6126,6129,6132,6134,6136],{"class":146,"line":837},[144,6120,5763],{"class":261},[144,6122,438],{"class":257},[144,6124,6125],{"class":158},"\"Maximum 9 images allowed, got ",[144,6127,6128],{"class":154},"{len",[144,6130,6131],{"class":261},"(image_urls)",[144,6133,689],{"class":154},[144,6135,447],{"class":158},[144,6137,404],{"class":261},[144,6139,6140,6142,6145,6147,6150],{"class":146,"line":843},[144,6141,4989],{"class":257},[144,6143,6144],{"class":261}," i, url ",[144,6146,1179],{"class":257},[144,6148,6149],{"class":154}," enumerate",[144,6151,6152],{"class":261},"(image_urls):\n",[144,6154,6155,6157,6159,6162,6165,6167,6170],{"class":146,"line":861},[144,6156,846],{"class":257},[144,6158,5750],{"class":257},[144,6160,6161],{"class":261}," url.startswith((",[144,6163,6164],{"class":158},"\"http://\"",[144,6166,398],{"class":261},[144,6168,6169],{"class":158},"\"https://\"",[144,6171,6172],{"class":261},")):\n",[144,6174,6175,6178,6180,6183,6185,6188,6190,6193],{"class":146,"line":870},[144,6176,6177],{"class":261},"            errors.append(",[144,6179,438],{"class":257},[144,6181,6182],{"class":158},"\"image_urls[",[144,6184,683],{"class":154},[144,6186,6187],{"class":261},"i",[144,6189,689],{"class":154},[144,6191,6192],{"class":158},"] must be an HTTP(S) URL\"",[144,6194,404],{"class":261},[144,6196,6197],{"class":146,"line":885},[144,6198,561],{"class":261},[144,6200,6201,6203],{"class":146,"line":901},[144,6202,2504],{"class":257},[144,6204,6205],{"class":261}," errors:\n",[144,6207,6208,6211,6213,6215,6217,6220,6222,6224,6227,6230,6232,6234,6237,6239,6242,6244,6246,6248,6250,6253,6256,6258],{"class":146,"line":913},[144,6209,6210],{"class":257},"        raise",[144,6212,5208],{"class":154},[144,6214,792],{"class":261},[144,6216,438],{"class":257},[144,6218,6219],{"class":158},"\"Payload validation failed:",[144,6221,1670],{"class":154},[144,6223,447],{"class":158},[144,6225,6226],{"class":257}," +",[144,6228,6229],{"class":158}," \"",[144,6231,1670],{"class":154},[144,6233,447],{"class":158},[144,6235,6236],{"class":261},".join(",[144,6238,438],{"class":257},[144,6240,6241],{"class":158},"\"  - ",[144,6243,683],{"class":154},[144,6245,5560],{"class":261},[144,6247,689],{"class":154},[144,6249,447],{"class":158},[144,6251,6252],{"class":257}," for",[144,6254,6255],{"class":261}," e ",[144,6257,1179],{"class":257},[144,6259,6260],{"class":261}," errors))\n",[144,6262,6263],{"class":146,"line":952},[144,6264,561],{"class":261},[144,6266,6267,6269],{"class":146,"line":958},[144,6268,1703],{"class":257},[144,6270,6271],{"class":154}," True\n",[17,6273,6274],{},[10,6275,6276,6278,6279,6282],{},[22,6277,303],{}," 画像 URL の特殊文字を URL エンコードし忘れること。画像パスにスペースや非 ASCII 文字が含まれる場合は、",[27,6280,6281],{},"urllib.parse.quote()"," でエンコードしてください。",[44,6284],{},[47,6286,6288],{"id":6287},"webhook-の設定polling-をスキップ","Webhook の設定（Polling をスキップ）",[10,6290,6291,6292,6295],{},"Polling はスクリプトやプロトタイピングには十分です。プロダクションシステムでは ",[22,6293,6294],{},"webhook"," がより効率的です — 動画が準備できたら API がサーバーに結果をプッシュします。無駄なリクエストなし、完了と通知の間の遅延もなし。",[91,6297,6298],{"id":6298},"仕組み",[10,6300,6301,6302,6304],{},"生成リクエストに ",[27,6303,3598],{}," を追加します：",[10,6306,6307],{},[2618,6308,6309],{},"上記の最初の例と同じセットアップを使用します。",[135,6311,6313],{"className":336,"code":6312,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": \"A spaceship launches from a desert landscape at sunset.\",\n    \"duration\": 8,\n    \"quality\": \"720p\",\n    \"callback_url\": \"https://your-server.com/api/webhook/seedance\"\n}\n\nresponse = requests.post(\n    f\"{BASE_URL}/videos/generations\",\n    headers=HEADERS,\n    json=payload\n)\ntask = response.json()\nprint(f\"Task submitted: {task['id']}\")\n# Polling 不要 — webhook が結果を受信します\n",[27,6314,6315,6323,6333,6344,6354,6364,6374,6378,6382,6391,6404,6415,6424,6428,6437,6463],{"__ignoreMap":140},[144,6316,6317,6319,6321],{"class":146,"line":147},[144,6318,3659],{"class":261},[144,6320,265],{"class":257},[144,6322,426],{"class":261},[144,6324,6325,6327,6329,6331],{"class":146,"line":165},[144,6326,3668],{"class":158},[144,6328,435],{"class":261},[144,6330,1308],{"class":158},[144,6332,450],{"class":261},[144,6334,6335,6337,6339,6342],{"class":146,"line":177},[144,6336,3679],{"class":158},[144,6338,435],{"class":261},[144,6340,6341],{"class":158},"\"A spaceship launches from a desert landscape at sunset.\"",[144,6343,450],{"class":261},[144,6345,6346,6348,6350,6352],{"class":146,"line":186},[144,6347,3691],{"class":158},[144,6349,435],{"class":261},[144,6351,3696],{"class":154},[144,6353,450],{"class":261},[144,6355,6356,6358,6360,6362],{"class":146,"line":371},[144,6357,3703],{"class":158},[144,6359,435],{"class":261},[144,6361,1368],{"class":158},[144,6363,450],{"class":261},[144,6365,6366,6369,6371],{"class":146,"line":377},[144,6367,6368],{"class":158},"    \"callback_url\"",[144,6370,435],{"class":261},[144,6372,6373],{"class":158},"\"https://your-server.com/api/webhook/seedance\"\n",[144,6375,6376],{"class":146,"line":383},[144,6377,467],{"class":261},[144,6379,6380],{"class":146,"line":407},[144,6381,374],{"emptyLinePlaceholder":57},[144,6383,6384,6387,6389],{"class":146,"line":418},[144,6385,6386],{"class":261},"response ",[144,6388,265],{"class":257},[144,6390,1432],{"class":261},[144,6392,6393,6396,6398,6400,6402],{"class":146,"line":429},[144,6394,6395],{"class":257},"    f",[144,6397,447],{"class":158},[144,6399,677],{"class":154},[144,6401,1444],{"class":158},[144,6403,450],{"class":261},[144,6405,6406,6409,6411,6413],{"class":146,"line":453},[144,6407,6408],{"class":699},"    headers",[144,6410,265],{"class":257},[144,6412,421],{"class":154},[144,6414,450],{"class":261},[144,6416,6417,6420,6422],{"class":146,"line":464},[144,6418,6419],{"class":699},"    json",[144,6421,265],{"class":257},[144,6423,2787],{"class":261},[144,6425,6426],{"class":146,"line":598},[144,6427,404],{"class":261},[144,6429,6430,6433,6435],{"class":146,"line":603},[144,6431,6432],{"class":261},"task ",[144,6434,265],{"class":257},[144,6436,734],{"class":261},[144,6438,6439,6442,6444,6446,6449,6451,6453,6455,6457,6459,6461],{"class":146,"line":609},[144,6440,6441],{"class":154},"print",[144,6443,792],{"class":261},[144,6445,438],{"class":257},[144,6447,6448],{"class":158},"\"Task submitted: ",[144,6450,683],{"class":154},[144,6452,1529],{"class":261},[144,6454,1532],{"class":158},[144,6456,1535],{"class":261},[144,6458,689],{"class":154},[144,6460,447],{"class":158},[144,6462,404],{"class":261},[144,6464,6465],{"class":146,"line":615},[144,6466,6467],{"class":173},"# Polling 不要 — webhook が結果を受信します\n",[10,6469,6470,6471,6473],{},"動画が準備できると、API が ",[27,6472,3598],{}," に完了した task オブジェクトを含む POST リクエストを送信します — polling で取得するものとまったく同じ内容です。",[91,6475,6477],{"id":6476},"webhook-の要件","Webhook の要件",[2036,6479,6480,6490],{},[2039,6481,6482],{},[2042,6483,6484,6487],{},[2045,6485,6486],{},"要件",[2045,6488,6489],{},"詳細",[2052,6491,6492,6500,6508,6516,6524,6532],{},[2042,6493,6494,6497],{},[2057,6495,6496],{},"プロトコル",[2057,6498,6499],{},"HTTPS のみ（HTTP 不可）— セキュリティ要件",[2042,6501,6502,6505],{},[2057,6503,6504],{},"レスポンス",[2057,6506,6507],{},"10 秒以内に 2xx を返す",[2042,6509,6510,6513],{},[2057,6511,6512],{},"リトライ",[2057,6514,6515],{},"失敗時 3 回リトライ（1 秒、2 秒、4 秒間隔）",[2042,6517,6518,6521],{},[2057,6519,6520],{},"URL 長",[2057,6522,6523],{},"≤ 2048 文字",[2042,6525,6526,6529],{},[2057,6527,6528],{},"ネットワーク",[2057,6530,6531],{},"内部/プライベート IP 不可（localhost、10.x.x.x、192.168.x.x）",[2042,6533,6534,6537],{},[2057,6535,6536],{},"ボディ",[2057,6538,6539],{},"完全な task オブジェクトを含む JSON POST",[91,6541,6543],{"id":6542},"プロダクション-flask-webhook-レシーバー","プロダクション Flask Webhook レシーバー",[10,6545,6546],{},"適切なバリデーション、エラー処理、非同期動画ダウンロードを備えた完全な webhook サーバー：",[135,6548,6550],{"className":336,"code":6549,"language":338,"meta":140,"style":140},"# webhook_server.py\n\"\"\"\nSeedance webhook レシーバー — 動画生成完了コールバックを処理します。\n実行：pip install flask requests\n      python webhook_server.py\n\"\"\"\nfrom flask import Flask, request, jsonify\nimport json\nimport os\nimport threading\nimport requests as req  # flask.request との競合を避けるためリネーム\n\napp = Flask(__name__)\n\n# 完了した動画を保存するディレクトリ\nOUTPUT_DIR = os.getenv(\"VIDEO_OUTPUT_DIR\", \"./videos\")\nos.makedirs(OUTPUT_DIR, exist_ok=True)\n\n\ndef download_video_async(video_url, task_id):\n    \"\"\"バックグラウンドスレッドで動画をダウンロードし、webhook のレスポンスをブロックしないようにします。\"\"\"\n    try:\n        filename = os.path.join(OUTPUT_DIR, f\"{task_id}.mp4\")\n        print(f\"  Downloading {task_id} to {filename}...\")\n        resp = req.get(video_url, stream=True, timeout=120)\n        resp.raise_for_status()\n        with open(filename, \"wb\") as f:\n            for chunk in resp.iter_content(chunk_size=8192):\n                f.write(chunk)\n        size_mb = os.path.getsize(filename) / (1024 * 1024)\n        print(f\"  Saved: {filename} ({size_mb:.1f} MB)\")\n    except Exception as e:\n        print(f\"  Download failed for {task_id}: {e}\")\n\n\n@app.route(\"/api/webhook/seedance\", methods=[\"POST\"])\ndef handle_webhook():\n    \"\"\"\n    Seedance 動画生成完了の webhook を処理します。\n    \n    動画生成が完了（成功または失敗）すると、\n    API が完全な task オブジェクトを含む POST を送信します。\n    \"\"\"\n    # 受信した task オブジェクトをパース\n    task = request.json\n    if not task:\n        return jsonify({\"error\": \"Empty body\"}), 400\n    \n    task_id = task.get(\"id\", \"unknown\")\n    status = task.get(\"status\", \"unknown\")\n    model = task.get(\"model\", \"unknown\")\n\n    print(f\"\\n{'='*50}\")\n    print(f\"Webhook received: task={task_id}\")\n    print(f\"  Status: {status}\")\n    print(f\"  Model: {model}\")\n\n    if status == \"completed\":\n        # results から動画 URL を抽出\n        results = task.get(\"results\", [])\n        if results:\n            video_url = results[0]\n            print(f\"  Video URL: {video_url}\")\n            \n            # バックグラウンドスレッドでダウンロードし、素早くレスポンス\n            thread = threading.Thread(\n                target=download_video_async,\n                args=(video_url, task_id)\n            )\n            thread.start()\n        else:\n            print(f\"  WARNING: Completed but no results array!\")\n\n    elif status == \"failed\":\n        error_info = task.get(\"error\", {})\n        print(f\"  FAILED: {json.dumps(error_info, indent=2)}\")\n        # TODO: エラートラッキングシステムに記録（Sentry など）\n        # TODO: オプションでパラメータを修正して再生成\n\n    else:\n        print(f\"  Unexpected status: {status}\")\n        print(f\"  Full payload: {json.dumps(task, indent=2)}\")\n\n    # 常に素早く 200 を返す — API は 10 秒以内のレスポンスを期待\n    return jsonify({\"received\": True, \"task_id\": task_id}), 200\n\n\n@app.route(\"/health\", methods=[\"GET\"])\ndef health_check():\n    \"\"\"ロードバランサー用ヘルスチェックエンドポイント。\"\"\"\n    return jsonify({\"status\": \"ok\"}), 200\n\n\nif __name__ == \"__main__\":\n    print(f\"Starting webhook server...\")\n    print(f\"Videos will be saved to: {os.path.abspath(OUTPUT_DIR)}\")\n    print(f\"Webhook URL: http://localhost:5000/api/webhook/seedance\")\n    app.run(host=\"0.0.0.0\", port=5000, debug=True)\n",[27,6551,6552,6557,6562,6567,6572,6577,6581,6594,6600,6606,6613,6628,6632,6647,6651,6656,6675,6693,6697,6701,6711,6716,6723,6752,6782,6809,6814,6831,6850,6855,6879,6912,6925,6954,6958,6962,6987,6996,7000,7005,7009,7014,7019,7023,7028,7037,7046,7067,7071,7089,7106,7123,7127,7153,7174,7195,7216,7220,7232,7237,7250,7257,7271,7293,7299,7305,7316,7327,7338,7343,7349,7357,7371,7376,7390,7404,7436,7448,7458,7463,7470,7492,7523,7528,7534,7559,7564,7569,7592,7602,7608,7626,7631,7636,7649,7663,7690,7704],{"__ignoreMap":140},[144,6553,6554],{"class":146,"line":147},[144,6555,6556],{"class":173},"# webhook_server.py\n",[144,6558,6559],{"class":146,"line":165},[144,6560,6561],{"class":158},"\"\"\"\n",[144,6563,6564],{"class":146,"line":177},[144,6565,6566],{"class":158},"Seedance webhook レシーバー — 動画生成完了コールバックを処理します。\n",[144,6568,6569],{"class":146,"line":186},[144,6570,6571],{"class":158},"実行：pip install flask requests\n",[144,6573,6574],{"class":146,"line":371},[144,6575,6576],{"class":158},"      python webhook_server.py\n",[144,6578,6579],{"class":146,"line":377},[144,6580,6561],{"class":158},[144,6582,6583,6586,6589,6591],{"class":146,"line":383},[144,6584,6585],{"class":257},"from",[144,6587,6588],{"class":261}," flask ",[144,6590,345],{"class":257},[144,6592,6593],{"class":261}," Flask, request, jsonify\n",[144,6595,6596,6598],{"class":146,"line":407},[144,6597,345],{"class":257},[144,6599,368],{"class":261},[144,6601,6602,6604],{"class":146,"line":418},[144,6603,345],{"class":257},[144,6605,361],{"class":261},[144,6607,6608,6610],{"class":146,"line":429},[144,6609,345],{"class":257},[144,6611,6612],{"class":261}," threading\n",[144,6614,6615,6617,6620,6622,6625],{"class":146,"line":453},[144,6616,345],{"class":257},[144,6618,6619],{"class":261}," requests ",[144,6621,1165],{"class":257},[144,6623,6624],{"class":261}," req  ",[144,6626,6627],{"class":173},"# flask.request との競合を避けるためリネーム\n",[144,6629,6630],{"class":146,"line":464},[144,6631,374],{"emptyLinePlaceholder":57},[144,6633,6634,6637,6639,6642,6645],{"class":146,"line":598},[144,6635,6636],{"class":261},"app ",[144,6638,265],{"class":257},[144,6640,6641],{"class":261}," Flask(",[144,6643,6644],{"class":154},"__name__",[144,6646,404],{"class":261},[144,6648,6649],{"class":146,"line":603},[144,6650,374],{"emptyLinePlaceholder":57},[144,6652,6653],{"class":146,"line":609},[144,6654,6655],{"class":173},"# 完了した動画を保存するディレクトリ\n",[144,6657,6658,6661,6663,6665,6668,6670,6673],{"class":146,"line":615},[144,6659,6660],{"class":154},"OUTPUT_DIR",[144,6662,389],{"class":257},[144,6664,392],{"class":261},[144,6666,6667],{"class":158},"\"VIDEO_OUTPUT_DIR\"",[144,6669,398],{"class":261},[144,6671,6672],{"class":158},"\"./videos\"",[144,6674,404],{"class":261},[144,6676,6677,6680,6682,6684,6687,6689,6691],{"class":146,"line":621},[144,6678,6679],{"class":261},"os.makedirs(",[144,6681,6660],{"class":154},[144,6683,398],{"class":261},[144,6685,6686],{"class":699},"exist_ok",[144,6688,265],{"class":257},[144,6690,1138],{"class":154},[144,6692,404],{"class":261},[144,6694,6695],{"class":146,"line":626},[144,6696,374],{"emptyLinePlaceholder":57},[144,6698,6699],{"class":146,"line":637},[144,6700,374],{"emptyLinePlaceholder":57},[144,6702,6703,6705,6708],{"class":146,"line":652},[144,6704,524],{"class":257},[144,6706,6707],{"class":150}," download_video_async",[144,6709,6710],{"class":261},"(video_url, task_id):\n",[144,6712,6713],{"class":146,"line":658},[144,6714,6715],{"class":158},"    \"\"\"バックグラウンドスレッドで動画をダウンロードし、webhook のレスポンスをブロックしないようにします。\"\"\"\n",[144,6717,6718,6721],{"class":146,"line":669},[144,6719,6720],{"class":257},"    try",[144,6722,858],{"class":261},[144,6724,6725,6728,6730,6733,6735,6737,6739,6741,6743,6745,6747,6750],{"class":146,"line":696},[144,6726,6727],{"class":261},"        filename ",[144,6729,265],{"class":257},[144,6731,6732],{"class":261}," os.path.join(",[144,6734,6660],{"class":154},[144,6736,398],{"class":261},[144,6738,438],{"class":257},[144,6740,447],{"class":158},[144,6742,683],{"class":154},[144,6744,686],{"class":261},[144,6746,689],{"class":154},[144,6748,6749],{"class":158},".mp4\"",[144,6751,404],{"class":261},[144,6753,6754,6756,6758,6760,6763,6765,6767,6769,6772,6774,6776,6778,6780],{"class":146,"line":708},[144,6755,789],{"class":154},[144,6757,792],{"class":261},[144,6759,438],{"class":257},[144,6761,6762],{"class":158},"\"  Downloading ",[144,6764,683],{"class":154},[144,6766,686],{"class":261},[144,6768,689],{"class":154},[144,6770,6771],{"class":158}," to ",[144,6773,683],{"class":154},[144,6775,1113],{"class":261},[144,6777,689],{"class":154},[144,6779,1118],{"class":158},[144,6781,404],{"class":261},[144,6783,6784,6787,6789,6792,6794,6796,6798,6800,6802,6804,6807],{"class":146,"line":714},[144,6785,6786],{"class":261},"        resp ",[144,6788,265],{"class":257},[144,6790,6791],{"class":261}," req.get(video_url, ",[144,6793,1133],{"class":699},[144,6795,265],{"class":257},[144,6797,1138],{"class":154},[144,6799,398],{"class":261},[144,6801,1018],{"class":699},[144,6803,265],{"class":257},[144,6805,6806],{"class":154},"120",[144,6808,404],{"class":261},[144,6810,6811],{"class":146,"line":720},[144,6812,6813],{"class":261},"        resp.raise_for_status()\n",[144,6815,6816,6819,6821,6823,6825,6827,6829],{"class":146,"line":726},[144,6817,6818],{"class":257},"        with",[144,6820,1153],{"class":154},[144,6822,1156],{"class":261},[144,6824,1159],{"class":158},[144,6826,1162],{"class":261},[144,6828,1165],{"class":257},[144,6830,1168],{"class":261},[144,6832,6833,6836,6838,6840,6842,6844,6846,6848],{"class":146,"line":737},[144,6834,6835],{"class":257},"            for",[144,6837,1176],{"class":261},[144,6839,1179],{"class":257},[144,6841,1182],{"class":261},[144,6843,1185],{"class":699},[144,6845,265],{"class":257},[144,6847,1190],{"class":154},[144,6849,546],{"class":261},[144,6851,6852],{"class":146,"line":742},[144,6853,6854],{"class":261},"                f.write(chunk)\n",[144,6856,6857,6860,6862,6865,6867,6869,6872,6875,6877],{"class":146,"line":748},[144,6858,6859],{"class":261},"        size_mb ",[144,6861,265],{"class":257},[144,6863,6864],{"class":261}," os.path.getsize(filename) ",[144,6866,1225],{"class":257},[144,6868,1217],{"class":261},[144,6870,6871],{"class":154},"1024",[144,6873,6874],{"class":257}," *",[144,6876,1228],{"class":154},[144,6878,404],{"class":261},[144,6880,6881,6883,6885,6887,6890,6892,6894,6896,6898,6900,6903,6905,6907,6910],{"class":146,"line":765},[144,6882,789],{"class":154},[144,6884,792],{"class":261},[144,6886,438],{"class":257},[144,6888,6889],{"class":158},"\"  Saved: ",[144,6891,683],{"class":154},[144,6893,1113],{"class":261},[144,6895,689],{"class":154},[144,6897,1217],{"class":158},[144,6899,683],{"class":154},[144,6901,6902],{"class":261},"size_mb",[144,6904,5359],{"class":257},[144,6906,689],{"class":154},[144,6908,6909],{"class":158}," MB)\"",[144,6911,404],{"class":261},[144,6913,6914,6917,6920,6923],{"class":146,"line":786},[144,6915,6916],{"class":257},"    except",[144,6918,6919],{"class":154}," Exception",[144,6921,6922],{"class":257}," as",[144,6924,5516],{"class":261},[144,6926,6927,6929,6931,6933,6936,6938,6940,6942,6944,6946,6948,6950,6952],{"class":146,"line":832},[144,6928,789],{"class":154},[144,6930,792],{"class":261},[144,6932,438],{"class":257},[144,6934,6935],{"class":158},"\"  Download failed for ",[144,6937,683],{"class":154},[144,6939,686],{"class":261},[144,6941,689],{"class":154},[144,6943,435],{"class":158},[144,6945,683],{"class":154},[144,6947,5560],{"class":261},[144,6949,689],{"class":154},[144,6951,447],{"class":158},[144,6953,404],{"class":261},[144,6955,6956],{"class":146,"line":837},[144,6957,374],{"emptyLinePlaceholder":57},[144,6959,6960],{"class":146,"line":843},[144,6961,374],{"emptyLinePlaceholder":57},[144,6963,6964,6967,6969,6972,6974,6977,6979,6982,6985],{"class":146,"line":861},[144,6965,6966],{"class":150},"@app.route",[144,6968,792],{"class":261},[144,6970,6971],{"class":158},"\"/api/webhook/seedance\"",[144,6973,398],{"class":261},[144,6975,6976],{"class":699},"methods",[144,6978,265],{"class":257},[144,6980,6981],{"class":261},"[",[144,6983,6984],{"class":158},"\"POST\"",[144,6986,1629],{"class":261},[144,6988,6989,6991,6994],{"class":146,"line":870},[144,6990,524],{"class":257},[144,6992,6993],{"class":150}," handle_webhook",[144,6995,1289],{"class":261},[144,6997,6998],{"class":146,"line":885},[144,6999,551],{"class":158},[144,7001,7002],{"class":146,"line":901},[144,7003,7004],{"class":158},"    Seedance 動画生成完了の webhook を処理します。\n",[144,7006,7007],{"class":146,"line":913},[144,7008,561],{"class":158},[144,7010,7011],{"class":146,"line":952},[144,7012,7013],{"class":158},"    動画生成が完了（成功または失敗）すると、\n",[144,7015,7016],{"class":146,"line":958},[144,7017,7018],{"class":158},"    API が完全な task オブジェクトを含む POST を送信します。\n",[144,7020,7021],{"class":146,"line":963},[144,7022,551],{"class":158},[144,7024,7025],{"class":146,"line":969},[144,7026,7027],{"class":173},"    # 受信した task オブジェクトをパース\n",[144,7029,7030,7032,7034],{"class":146,"line":975},[144,7031,1496],{"class":261},[144,7033,265],{"class":257},[144,7035,7036],{"class":261}," request.json\n",[144,7038,7039,7041,7043],{"class":146,"line":987},[144,7040,2504],{"class":257},[144,7042,5750],{"class":257},[144,7044,7045],{"class":261}," task:\n",[144,7047,7048,7051,7054,7056,7058,7061,7064],{"class":146,"line":992},[144,7049,7050],{"class":257},"        return",[144,7052,7053],{"class":261}," jsonify({",[144,7055,895],{"class":158},[144,7057,435],{"class":261},[144,7059,7060],{"class":158},"\"Empty body\"",[144,7062,7063],{"class":261},"}), ",[144,7065,7066],{"class":154},"400\n",[144,7068,7069],{"class":146,"line":5401},[144,7070,561],{"class":261},[144,7072,7073,7076,7078,7080,7082,7084,7087],{"class":146,"line":5410},[144,7074,7075],{"class":261},"    task_id ",[144,7077,265],{"class":257},[144,7079,773],{"class":261},[144,7081,1626],{"class":158},[144,7083,398],{"class":261},[144,7085,7086],{"class":158},"\"unknown\"",[144,7088,404],{"class":261},[144,7090,7091,7094,7096,7098,7100,7102,7104],{"class":146,"line":5438},[144,7092,7093],{"class":261},"    status ",[144,7095,265],{"class":257},[144,7097,773],{"class":261},[144,7099,759],{"class":158},[144,7101,398],{"class":261},[144,7103,7086],{"class":158},[144,7105,404],{"class":261},[144,7107,7108,7111,7113,7115,7117,7119,7121],{"class":146,"line":5469},[144,7109,7110],{"class":261},"    model ",[144,7112,265],{"class":257},[144,7114,773],{"class":261},[144,7116,5756],{"class":158},[144,7118,398],{"class":261},[144,7120,7086],{"class":158},[144,7122,404],{"class":261},[144,7124,7125],{"class":146,"line":5489},[144,7126,374],{"emptyLinePlaceholder":57},[144,7128,7129,7131,7133,7135,7137,7140,7143,7146,7149,7151],{"class":146,"line":5495},[144,7130,1101],{"class":154},[144,7132,792],{"class":261},[144,7134,438],{"class":257},[144,7136,447],{"class":158},[144,7138,7139],{"class":154},"\\n{",[144,7141,7142],{"class":158},"'='",[144,7144,7145],{"class":257},"*",[144,7147,7148],{"class":154},"50}",[144,7150,447],{"class":158},[144,7152,404],{"class":261},[144,7154,7155,7157,7159,7161,7164,7166,7168,7170,7172],{"class":146,"line":5501},[144,7156,1101],{"class":154},[144,7158,792],{"class":261},[144,7160,438],{"class":257},[144,7162,7163],{"class":158},"\"Webhook received: task=",[144,7165,683],{"class":154},[144,7167,686],{"class":261},[144,7169,689],{"class":154},[144,7171,447],{"class":158},[144,7173,404],{"class":261},[144,7175,7176,7178,7180,7182,7185,7187,7189,7191,7193],{"class":146,"line":5506},[144,7177,1101],{"class":154},[144,7179,792],{"class":261},[144,7181,438],{"class":257},[144,7183,7184],{"class":158},"\"  Status: ",[144,7186,683],{"class":154},[144,7188,812],{"class":261},[144,7190,689],{"class":154},[144,7192,447],{"class":158},[144,7194,404],{"class":261},[144,7196,7197,7199,7201,7203,7206,7208,7210,7212,7214],{"class":146,"line":5519},[144,7198,1101],{"class":154},[144,7200,792],{"class":261},[144,7202,438],{"class":257},[144,7204,7205],{"class":158},"\"  Model: ",[144,7207,683],{"class":154},[144,7209,1747],{"class":261},[144,7211,689],{"class":154},[144,7213,447],{"class":158},[144,7215,404],{"class":261},[144,7217,7218],{"class":146,"line":5546},[144,7219,374],{"emptyLinePlaceholder":57},[144,7221,7222,7224,7226,7228,7230],{"class":146,"line":5586},[144,7223,2504],{"class":257},[144,7225,849],{"class":261},[144,7227,852],{"class":257},[144,7229,855],{"class":158},[144,7231,858],{"class":261},[144,7233,7234],{"class":146,"line":5605},[144,7235,7236],{"class":173},"        # results から動画 URL を抽出\n",[144,7238,7239,7242,7244,7246,7248],{"class":146,"line":5610},[144,7240,7241],{"class":261},"        results ",[144,7243,265],{"class":257},[144,7245,773],{"class":261},[144,7247,1651],{"class":158},[144,7249,6099],{"class":261},[144,7251,7252,7254],{"class":146,"line":5615},[144,7253,846],{"class":257},[144,7255,7256],{"class":261}," results:\n",[144,7258,7259,7262,7264,7267,7269],{"class":146,"line":5620},[144,7260,7261],{"class":261},"            video_url ",[144,7263,265],{"class":257},[144,7265,7266],{"class":261}," results[",[144,7268,781],{"class":154},[144,7270,762],{"class":261},[144,7272,7274,7276,7278,7280,7283,7285,7287,7289,7291],{"class":146,"line":7273},63,[144,7275,5441],{"class":154},[144,7277,792],{"class":261},[144,7279,438],{"class":257},[144,7281,7282],{"class":158},"\"  Video URL: ",[144,7284,683],{"class":154},[144,7286,1678],{"class":261},[144,7288,689],{"class":154},[144,7290,447],{"class":158},[144,7292,404],{"class":261},[144,7294,7296],{"class":146,"line":7295},64,[144,7297,7298],{"class":261},"            \n",[144,7300,7302],{"class":146,"line":7301},65,[144,7303,7304],{"class":173},"            # バックグラウンドスレッドでダウンロードし、素早くレスポンス\n",[144,7306,7308,7311,7313],{"class":146,"line":7307},66,[144,7309,7310],{"class":261},"            thread ",[144,7312,265],{"class":257},[144,7314,7315],{"class":261}," threading.Thread(\n",[144,7317,7319,7322,7324],{"class":146,"line":7318},67,[144,7320,7321],{"class":699},"                target",[144,7323,265],{"class":257},[144,7325,7326],{"class":261},"download_video_async,\n",[144,7328,7330,7333,7335],{"class":146,"line":7329},68,[144,7331,7332],{"class":699},"                args",[144,7334,265],{"class":257},[144,7336,7337],{"class":261},"(video_url, task_id)\n",[144,7339,7341],{"class":146,"line":7340},69,[144,7342,955],{"class":261},[144,7344,7346],{"class":146,"line":7345},70,[144,7347,7348],{"class":261},"            thread.start()\n",[144,7350,7352,7355],{"class":146,"line":7351},71,[144,7353,7354],{"class":257},"        else",[144,7356,858],{"class":261},[144,7358,7360,7362,7364,7366,7369],{"class":146,"line":7359},72,[144,7361,5441],{"class":154},[144,7363,792],{"class":261},[144,7365,438],{"class":257},[144,7367,7368],{"class":158},"\"  WARNING: Completed but no results array!\"",[144,7370,404],{"class":261},[144,7372,7374],{"class":146,"line":7373},73,[144,7375,374],{"emptyLinePlaceholder":57},[144,7377,7379,7382,7384,7386,7388],{"class":146,"line":7378},74,[144,7380,7381],{"class":257},"    elif",[144,7383,849],{"class":261},[144,7385,852],{"class":257},[144,7387,880],{"class":158},[144,7389,858],{"class":261},[144,7391,7393,7396,7398,7400,7402],{"class":146,"line":7392},75,[144,7394,7395],{"class":261},"        error_info ",[144,7397,265],{"class":257},[144,7399,773],{"class":261},[144,7401,895],{"class":158},[144,7403,898],{"class":261},[144,7405,7407,7409,7411,7413,7416,7418,7421,7424,7426,7428,7430,7432,7434],{"class":146,"line":7406},76,[144,7408,789],{"class":154},[144,7410,792],{"class":261},[144,7412,438],{"class":257},[144,7414,7415],{"class":158},"\"  FAILED: ",[144,7417,683],{"class":154},[144,7419,7420],{"class":261},"json.dumps(error_info, ",[144,7422,7423],{"class":699},"indent",[144,7425,265],{"class":257},[144,7427,5288],{"class":154},[144,7429,944],{"class":261},[144,7431,689],{"class":154},[144,7433,447],{"class":158},[144,7435,404],{"class":261},[144,7437,7439,7442,7445],{"class":146,"line":7438},77,[144,7440,7441],{"class":173},"        # ",[144,7443,7444],{"class":257},"TODO",[144,7446,7447],{"class":173},": エラートラッキングシステムに記録（Sentry など）\n",[144,7449,7451,7453,7455],{"class":146,"line":7450},78,[144,7452,7441],{"class":173},[144,7454,7444],{"class":257},[144,7456,7457],{"class":173},": オプションでパラメータを修正して再生成\n",[144,7459,7461],{"class":146,"line":7460},79,[144,7462,374],{"emptyLinePlaceholder":57},[144,7464,7466,7468],{"class":146,"line":7465},80,[144,7467,2540],{"class":257},[144,7469,858],{"class":261},[144,7471,7473,7475,7477,7479,7482,7484,7486,7488,7490],{"class":146,"line":7472},81,[144,7474,789],{"class":154},[144,7476,792],{"class":261},[144,7478,438],{"class":257},[144,7480,7481],{"class":158},"\"  Unexpected status: ",[144,7483,683],{"class":154},[144,7485,812],{"class":261},[144,7487,689],{"class":154},[144,7489,447],{"class":158},[144,7491,404],{"class":261},[144,7493,7495,7497,7499,7501,7504,7506,7509,7511,7513,7515,7517,7519,7521],{"class":146,"line":7494},82,[144,7496,789],{"class":154},[144,7498,792],{"class":261},[144,7500,438],{"class":257},[144,7502,7503],{"class":158},"\"  Full payload: ",[144,7505,683],{"class":154},[144,7507,7508],{"class":261},"json.dumps(task, ",[144,7510,7423],{"class":699},[144,7512,265],{"class":257},[144,7514,5288],{"class":154},[144,7516,944],{"class":261},[144,7518,689],{"class":154},[144,7520,447],{"class":158},[144,7522,404],{"class":261},[144,7524,7526],{"class":146,"line":7525},83,[144,7527,374],{"emptyLinePlaceholder":57},[144,7529,7531],{"class":146,"line":7530},84,[144,7532,7533],{"class":173},"    # 常に素早く 200 を返す — API は 10 秒以内のレスポンスを期待\n",[144,7535,7537,7539,7541,7544,7546,7548,7550,7553,7556],{"class":146,"line":7536},85,[144,7538,1703],{"class":257},[144,7540,7053],{"class":261},[144,7542,7543],{"class":158},"\"received\"",[144,7545,435],{"class":261},[144,7547,1138],{"class":154},[144,7549,398],{"class":261},[144,7551,7552],{"class":158},"\"task_id\"",[144,7554,7555],{"class":261},": task_id}), ",[144,7557,7558],{"class":154},"200\n",[144,7560,7562],{"class":146,"line":7561},86,[144,7563,374],{"emptyLinePlaceholder":57},[144,7565,7567],{"class":146,"line":7566},87,[144,7568,374],{"emptyLinePlaceholder":57},[144,7570,7572,7574,7576,7579,7581,7583,7585,7587,7590],{"class":146,"line":7571},88,[144,7573,6966],{"class":150},[144,7575,792],{"class":261},[144,7577,7578],{"class":158},"\"/health\"",[144,7580,398],{"class":261},[144,7582,6976],{"class":699},[144,7584,265],{"class":257},[144,7586,6981],{"class":261},[144,7588,7589],{"class":158},"\"GET\"",[144,7591,1629],{"class":261},[144,7593,7595,7597,7600],{"class":146,"line":7594},89,[144,7596,524],{"class":257},[144,7598,7599],{"class":150}," health_check",[144,7601,1289],{"class":261},[144,7603,7605],{"class":146,"line":7604},90,[144,7606,7607],{"class":158},"    \"\"\"ロードバランサー用ヘルスチェックエンドポイント。\"\"\"\n",[144,7609,7611,7613,7615,7617,7619,7622,7624],{"class":146,"line":7610},91,[144,7612,1703],{"class":257},[144,7614,7053],{"class":261},[144,7616,759],{"class":158},[144,7618,435],{"class":261},[144,7620,7621],{"class":158},"\"ok\"",[144,7623,7063],{"class":261},[144,7625,7558],{"class":154},[144,7627,7629],{"class":146,"line":7628},92,[144,7630,374],{"emptyLinePlaceholder":57},[144,7632,7634],{"class":146,"line":7633},93,[144,7635,374],{"emptyLinePlaceholder":57},[144,7637,7639,7641,7643,7645,7647],{"class":146,"line":7638},94,[144,7640,1719],{"class":257},[144,7642,1722],{"class":154},[144,7644,1725],{"class":257},[144,7646,1728],{"class":158},[144,7648,858],{"class":261},[144,7650,7652,7654,7656,7658,7661],{"class":146,"line":7651},95,[144,7653,1101],{"class":154},[144,7655,792],{"class":261},[144,7657,438],{"class":257},[144,7659,7660],{"class":158},"\"Starting webhook server...\"",[144,7662,404],{"class":261},[144,7664,7666,7668,7670,7672,7675,7677,7680,7682,7684,7686,7688],{"class":146,"line":7665},96,[144,7667,1101],{"class":154},[144,7669,792],{"class":261},[144,7671,438],{"class":257},[144,7673,7674],{"class":158},"\"Videos will be saved to: ",[144,7676,683],{"class":154},[144,7678,7679],{"class":261},"os.path.abspath(",[144,7681,6660],{"class":154},[144,7683,944],{"class":261},[144,7685,689],{"class":154},[144,7687,447],{"class":158},[144,7689,404],{"class":261},[144,7691,7693,7695,7697,7699,7702],{"class":146,"line":7692},97,[144,7694,1101],{"class":154},[144,7696,792],{"class":261},[144,7698,438],{"class":257},[144,7700,7701],{"class":158},"\"Webhook URL: http://localhost:5000/api/webhook/seedance\"",[144,7703,404],{"class":261},[144,7705,7707,7710,7713,7715,7718,7720,7723,7725,7728,7730,7733,7735,7737],{"class":146,"line":7706},98,[144,7708,7709],{"class":261},"    app.run(",[144,7711,7712],{"class":699},"host",[144,7714,265],{"class":257},[144,7716,7717],{"class":158},"\"0.0.0.0\"",[144,7719,398],{"class":261},[144,7721,7722],{"class":699},"port",[144,7724,265],{"class":257},[144,7726,7727],{"class":154},"5000",[144,7729,398],{"class":261},[144,7731,7732],{"class":699},"debug",[144,7734,265],{"class":257},[144,7736,1138],{"class":154},[144,7738,404],{"class":261},[10,7740,7741],{},"依存関係のインストールと実行：",[135,7743,7745],{"className":137,"code":7744,"language":139,"meta":140,"style":140},"pip install flask requests\npython webhook_server.py\n",[27,7746,7747,7758],{"__ignoreMap":140},[144,7748,7749,7751,7753,7756],{"class":146,"line":147},[144,7750,189],{"class":150},[144,7752,192],{"class":158},[144,7754,7755],{"class":158}," flask",[144,7757,327],{"class":158},[144,7759,7760,7762],{"class":146,"line":165},[144,7761,338],{"class":150},[144,7763,7764],{"class":158}," webhook_server.py\n",[10,7766,7767],{},"このサーバーの主な設計判断：",[95,7769,7770,7780,7789],{},[72,7771,7772,7775,7776,7779],{},[22,7773,7774],{},"バックグラウンドダウンロード"," — スレッドを生成して動画をダウンロードするため、webhook ハンドラーは即座に ",[27,7777,7778],{},"200"," を返します。API は 10 秒以内のレスポンスを期待しますが、動画のダウンロードはそれ以上かかる場合があります。",[72,7781,7782,1060,7785,7788],{},[22,7783,7784],{},"ヘルスチェックエンドポイント",[27,7786,7787],{},"/health"," はロードバランサー（ALB、nginx など）の背後にデプロイする際に便利です。",[72,7790,7791,7794],{},[22,7792,7793],{},"エラーログ"," — 失敗したタスクは完全なエラー payload とともに出力されます。プロダクションでは Sentry、Datadog、またはログスタックに接続してください。",[91,7796,7798],{"id":7797},"ngrok-でローカルホストを公開","ngrok でローカルホストを公開",[10,7800,7801,7802,7807],{},"ローカル開発時、",[36,7803,7806],{"href":7804,"rel":7805},"https://ngrok.com",[40],"ngrok"," を使ってローカルサーバーへのトンネルとなる公開 HTTPS URL を作成します：",[135,7809,7811],{"className":137,"code":7810,"language":139,"meta":140,"style":140},"# ngrok のインストール（macOS）\nbrew install ngrok\n\n# または https://ngrok.com/download からダウンロード\n\n# トンネルを開始\nngrok http 5000\n",[27,7812,7813,7818,7828,7832,7837,7841,7846],{"__ignoreMap":140},[144,7814,7815],{"class":146,"line":147},[144,7816,7817],{"class":173},"# ngrok のインストール（macOS）\n",[144,7819,7820,7823,7825],{"class":146,"line":165},[144,7821,7822],{"class":150},"brew",[144,7824,192],{"class":158},[144,7826,7827],{"class":158}," ngrok\n",[144,7829,7830],{"class":146,"line":177},[144,7831,374],{"emptyLinePlaceholder":57},[144,7833,7834],{"class":146,"line":186},[144,7835,7836],{"class":173},"# または https://ngrok.com/download からダウンロード\n",[144,7838,7839],{"class":146,"line":371},[144,7840,374],{"emptyLinePlaceholder":57},[144,7842,7843],{"class":146,"line":377},[144,7844,7845],{"class":173},"# トンネルを開始\n",[144,7847,7848,7850,7853],{"class":146,"line":383},[144,7849,7806],{"class":150},[144,7851,7852],{"class":158}," http",[144,7854,7855],{"class":154}," 5000\n",[10,7857,7858],{},"ngrok の出力例：",[135,7860,7863],{"className":7861,"code":7862,"language":2185},[2183],"Forwarding  https://a1b2c3d4.ngrok-free.app → http://localhost:5000\n",[27,7864,7862],{"__ignoreMap":140},[10,7866,7867,7868,7870],{},"この HTTPS URL を ",[27,7869,3598],{}," として使用します：",[135,7872,7874],{"className":336,"code":7873,"language":338,"meta":140,"style":140},"payload = {\n    \"model\": \"seedance-2.0\",\n    \"prompt\": \"Your prompt here\",\n    \"callback_url\": \"https://a1b2c3d4.ngrok-free.app/api/webhook/seedance\"\n}\n",[27,7875,7876,7884,7894,7905,7914],{"__ignoreMap":140},[144,7877,7878,7880,7882],{"class":146,"line":147},[144,7879,3659],{"class":261},[144,7881,265],{"class":257},[144,7883,426],{"class":261},[144,7885,7886,7888,7890,7892],{"class":146,"line":165},[144,7887,3668],{"class":158},[144,7889,435],{"class":261},[144,7891,1308],{"class":158},[144,7893,450],{"class":261},[144,7895,7896,7898,7900,7903],{"class":146,"line":177},[144,7897,3679],{"class":158},[144,7899,435],{"class":261},[144,7901,7902],{"class":158},"\"Your prompt here\"",[144,7904,450],{"class":261},[144,7906,7907,7909,7911],{"class":146,"line":186},[144,7908,6368],{"class":158},[144,7910,435],{"class":261},[144,7912,7913],{"class":158},"\"https://a1b2c3d4.ngrok-free.app/api/webhook/seedance\"\n",[144,7915,7916],{"class":146,"line":371},[144,7917,467],{"class":261},[17,7919,7920],{},[10,7921,7922,7924,7925,7928,7929,7932],{},[22,7923,303],{}," ngrok の ",[27,7926,7927],{},"https://"," URL ではなく ",[27,7930,7931],{},"http://"," URL を使用すること。Seedance API は webhook に HTTPS を要求します — プレーン HTTP のコールバック URL は 400 エラーを返します。",[91,7934,7936],{"id":7935},"webhook-のセキュリティ","Webhook のセキュリティ",[10,7938,7939],{},"プロダクションでは、webhook リクエストが実際に EvoLink API から来ていることを検証してください：",[135,7941,7943],{"className":336,"code":7942,"language":338,"meta":140,"style":140},"import hmac\nimport hashlib\n\ndef verify_webhook(request):\n    \"\"\"タスク ID パターンで webhook の真正性を検証します。\"\"\"\n    task = request.json\n    task_id = task.get(\"id\", \"\")\n    \n    # EvoLink のタスク ID は特定のフォーマットに従います\n    if not task_id.startswith(\"task-unified-\"):\n        return False\n    \n    # 追加バリデーション：必須フィールドの存在を確認\n    required_fields = [\"id\", \"status\", \"model\", \"created\"]\n    if not all(field in task for field in required_fields):\n        return False\n    \n    return True\n",[27,7944,7945,7952,7959,7963,7973,7978,7986,8002,8006,8011,8025,8032,8036,8041,8068,8096,8102,8106],{"__ignoreMap":140},[144,7946,7947,7949],{"class":146,"line":147},[144,7948,345],{"class":257},[144,7950,7951],{"class":261}," hmac\n",[144,7953,7954,7956],{"class":146,"line":165},[144,7955,345],{"class":257},[144,7957,7958],{"class":261}," hashlib\n",[144,7960,7961],{"class":146,"line":177},[144,7962,374],{"emptyLinePlaceholder":57},[144,7964,7965,7967,7970],{"class":146,"line":186},[144,7966,524],{"class":257},[144,7968,7969],{"class":150}," verify_webhook",[144,7971,7972],{"class":261},"(request):\n",[144,7974,7975],{"class":146,"line":371},[144,7976,7977],{"class":158},"    \"\"\"タスク ID パターンで webhook の真正性を検証します。\"\"\"\n",[144,7979,7980,7982,7984],{"class":146,"line":377},[144,7981,1496],{"class":261},[144,7983,265],{"class":257},[144,7985,7036],{"class":261},[144,7987,7988,7990,7992,7994,7996,7998,8000],{"class":146,"line":383},[144,7989,7075],{"class":261},[144,7991,265],{"class":257},[144,7993,773],{"class":261},[144,7995,1626],{"class":158},[144,7997,398],{"class":261},[144,7999,5136],{"class":158},[144,8001,404],{"class":261},[144,8003,8004],{"class":146,"line":407},[144,8005,561],{"class":261},[144,8007,8008],{"class":146,"line":418},[144,8009,8010],{"class":173},"    # EvoLink のタスク ID は特定のフォーマットに従います\n",[144,8012,8013,8015,8017,8020,8023],{"class":146,"line":429},[144,8014,2504],{"class":257},[144,8016,5750],{"class":257},[144,8018,8019],{"class":261}," task_id.startswith(",[144,8021,8022],{"class":158},"\"task-unified-\"",[144,8024,546],{"class":261},[144,8026,8027,8029],{"class":146,"line":453},[144,8028,7050],{"class":257},[144,8030,8031],{"class":154}," False\n",[144,8033,8034],{"class":146,"line":464},[144,8035,561],{"class":261},[144,8037,8038],{"class":146,"line":598},[144,8039,8040],{"class":173},"    # 追加バリデーション：必須フィールドの存在を確認\n",[144,8042,8043,8046,8048,8051,8053,8055,8057,8059,8061,8063,8066],{"class":146,"line":603},[144,8044,8045],{"class":261},"    required_fields ",[144,8047,265],{"class":257},[144,8049,8050],{"class":261}," [",[144,8052,1626],{"class":158},[144,8054,398],{"class":261},[144,8056,759],{"class":158},[144,8058,398],{"class":261},[144,8060,5756],{"class":158},[144,8062,398],{"class":261},[144,8064,8065],{"class":158},"\"created\"",[144,8067,762],{"class":261},[144,8069,8070,8072,8074,8077,8080,8082,8085,8088,8091,8093],{"class":146,"line":609},[144,8071,2504],{"class":257},[144,8073,5750],{"class":257},[144,8075,8076],{"class":154}," all",[144,8078,8079],{"class":261},"(field ",[144,8081,1179],{"class":257},[144,8083,8084],{"class":261}," task ",[144,8086,8087],{"class":257},"for",[144,8089,8090],{"class":261}," field ",[144,8092,1179],{"class":257},[144,8094,8095],{"class":261}," required_fields):\n",[144,8097,8098,8100],{"class":146,"line":615},[144,8099,7050],{"class":257},[144,8101,8031],{"class":154},[144,8103,8104],{"class":146,"line":621},[144,8105,561],{"class":261},[144,8107,8108,8110],{"class":146,"line":626},[144,8109,1703],{"class":257},[144,8111,6271],{"class":154},[91,8113,8115],{"id":8114},"webhook-vs-pollingどちらを選ぶか","Webhook vs Polling：どちらを選ぶか？",[2036,8117,8118,8131],{},[2039,8119,8120],{},[2042,8121,8122,8125,8128],{},[2045,8123,8124],{},"シナリオ",[2045,8126,8127],{},"推奨",[2045,8129,8130],{},"理由",[2052,8132,8133,8143,8154,8165,8175,8185],{},[2042,8134,8135,8138,8140],{},[2057,8136,8137],{},"クイックプロトタイピング / スクリプト",[2057,8139,2242],{},[2057,8141,8142],{},"シンプル、サーバー不要",[2042,8144,8145,8148,8151],{},[2057,8146,8147],{},"プロダクション Web アプリ",[2057,8149,8150],{},"Webhook",[2057,8152,8153],{},"スケーラブル、リクエストの無駄なし",[2042,8155,8156,8159,8162],{},[2057,8157,8158],{},"バッチ処理（100+ 動画）",[2057,8160,8161],{},"Webhook + キュー",[2057,8163,8164],{},"すべて送信、完了順に処理",[2042,8166,8167,8170,8172],{},[2057,8168,8169],{},"CLI ツール",[2057,8171,2242],{},[2057,8173,8174],{},"サーバーインフラ不要",[2042,8176,8177,8180,8182],{},[2057,8178,8179],{},"モバイルアプリバックエンド",[2057,8181,8150],{},[2057,8183,8184],{},"完了時にユーザーにプッシュ通知",[2042,8186,8187,8190,8192],{},[2057,8188,8189],{},"サーバーレス（Lambda/Cloud Functions）",[2057,8191,8150],{},[2057,8193,8194],{},"完璧にマッチ — 完了ごとに関数がトリガー",[17,8196,8197],{},[10,8198,8199,8201],{},[22,8200,132],{}," バッチ処理では、webhook とメッセージキュー（Redis、RabbitMQ、SQS）を組み合わせてください。すべての生成リクエストを送信し、キューに到着した順に処理します。これにより送信と処理が分離され、リトライも適切に処理できます。",[44,8203],{},[47,8205,8207],{"id":8206},"バッチ処理複数の動画を生成する","バッチ処理：複数の動画を生成する",[10,8209,8210],{},"実際のユースケースでは多数の動画を生成することがよくあります。レート制限を考慮したバッチ処理パターンを紹介します：",[10,8212,8213],{},[2618,8214,8215],{},"上記の最初の例と同じセットアップとヘルパー関数を使用します。",[135,8217,8219],{"className":336,"code":8218,"language":338,"meta":140,"style":140},"import concurrent.futures\n\ndef batch_generate(prompts, max_concurrent=3):\n    \"\"\"\n    並行性を制御して複数の動画を生成します。\n    \n    Args:\n        prompts: プロンプト文字列のリスト。\n        max_concurrent: 最大同時生成数。\n    \n    Returns:\n        (prompt, result_or_error) タプルのリスト。\n    \"\"\"\n    results = []\n    \n    def generate_one(prompt, index):\n        \"\"\"1 つの動画を生成して結果を返します。\"\"\"\n        payload = {\n            \"model\": \"seedance-2.0\",\n            \"prompt\": prompt,\n            \"duration\": 5,\n            \"quality\": \"720p\"\n        }\n        try:\n            task = generate_video_with_retry(payload)\n            print(f\"[{index}] Submitted: {task['id']}\")\n            result = wait_for_video(task[\"id\"])\n            video_url = result[\"results\"][0]\n            download_video(video_url, f\"batch_{index}.mp4\")\n            return (prompt, result)\n        except Exception as e:\n            print(f\"[{index}] Failed: {e}\")\n            return (prompt, str(e))\n    \n    # レート制限を尊重してバッチで処理\n    with concurrent.futures.ThreadPoolExecutor(max_workers=max_concurrent) as executor:\n        futures = {\n            executor.submit(generate_one, prompt, i): i\n            for i, prompt in enumerate(prompts)\n        }\n        for future in concurrent.futures.as_completed(futures):\n            results.append(future.result())\n    \n    # サマリー\n    succeeded = sum(1 for _, r in results if isinstance(r, dict))\n    print(f\"\\nBatch complete: {succeeded}/{len(prompts)} succeeded\")\n    return results\n\n\n# 使用例\nprompts = [\n    \"A hummingbird hovering near a red flower. Macro lens, shallow depth of field.\",\n    \"Ocean waves crashing on volcanic rocks at sunset. Slow motion.\",\n    \"A street musician playing violin in the rain. Cinematic lighting.\",\n]\nbatch_generate(prompts, max_concurrent=2)\n",[27,8220,8221,8228,8232,8248,8252,8257,8261,8265,8270,8275,8279,8283,8288,8292,8301,8305,8316,8321,8330,8341,8349,8360,8370,8375,8381,8391,8426,8439,8455,8475,8482,8492,8521,8534,8538,8543,8563,8572,8577,8591,8595,8607,8612,8616,8621,8659,8695,8702,8706,8710,8715,8725,8732,8739,8746,8750],{"__ignoreMap":140},[144,8222,8223,8225],{"class":146,"line":147},[144,8224,345],{"class":257},[144,8226,8227],{"class":261}," concurrent.futures\n",[144,8229,8230],{"class":146,"line":165},[144,8231,374],{"emptyLinePlaceholder":57},[144,8233,8234,8236,8239,8242,8244,8246],{"class":146,"line":177},[144,8235,524],{"class":257},[144,8237,8238],{"class":150}," batch_generate",[144,8240,8241],{"class":261},"(prompts, max_concurrent",[144,8243,265],{"class":257},[144,8245,4926],{"class":154},[144,8247,546],{"class":261},[144,8249,8250],{"class":146,"line":186},[144,8251,551],{"class":158},[144,8253,8254],{"class":146,"line":371},[144,8255,8256],{"class":158},"    並行性を制御して複数の動画を生成します。\n",[144,8258,8259],{"class":146,"line":377},[144,8260,561],{"class":158},[144,8262,8263],{"class":146,"line":383},[144,8264,566],{"class":158},[144,8266,8267],{"class":146,"line":407},[144,8268,8269],{"class":158},"        prompts: プロンプト文字列のリスト。\n",[144,8271,8272],{"class":146,"line":418},[144,8273,8274],{"class":158},"        max_concurrent: 最大同時生成数。\n",[144,8276,8277],{"class":146,"line":429},[144,8278,561],{"class":158},[144,8280,8281],{"class":146,"line":453},[144,8282,590],{"class":158},[144,8284,8285],{"class":146,"line":464},[144,8286,8287],{"class":158},"        (prompt, result_or_error) タプルのリスト。\n",[144,8289,8290],{"class":146,"line":598},[144,8291,551],{"class":158},[144,8293,8294,8297,8299],{"class":146,"line":603},[144,8295,8296],{"class":261},"    results ",[144,8298,265],{"class":257},[144,8300,5734],{"class":261},[144,8302,8303],{"class":146,"line":609},[144,8304,561],{"class":261},[144,8306,8307,8310,8313],{"class":146,"line":615},[144,8308,8309],{"class":257},"    def",[144,8311,8312],{"class":150}," generate_one",[144,8314,8315],{"class":261},"(prompt, index):\n",[144,8317,8318],{"class":146,"line":621},[144,8319,8320],{"class":158},"        \"\"\"1 つの動画を生成して結果を返します。\"\"\"\n",[144,8322,8323,8326,8328],{"class":146,"line":626},[144,8324,8325],{"class":261},"        payload ",[144,8327,265],{"class":257},[144,8329,426],{"class":261},[144,8331,8332,8335,8337,8339],{"class":146,"line":637},[144,8333,8334],{"class":158},"            \"model\"",[144,8336,435],{"class":261},[144,8338,1308],{"class":158},[144,8340,450],{"class":261},[144,8342,8343,8346],{"class":146,"line":652},[144,8344,8345],{"class":158},"            \"prompt\"",[144,8347,8348],{"class":261},": prompt,\n",[144,8350,8351,8354,8356,8358],{"class":146,"line":658},[144,8352,8353],{"class":158},"            \"duration\"",[144,8355,435],{"class":261},[144,8357,1352],{"class":154},[144,8359,450],{"class":261},[144,8361,8362,8365,8367],{"class":146,"line":669},[144,8363,8364],{"class":158},"            \"quality\"",[144,8366,435],{"class":261},[144,8368,8369],{"class":158},"\"720p\"\n",[144,8371,8372],{"class":146,"line":696},[144,8373,8374],{"class":261},"        }\n",[144,8376,8377,8379],{"class":146,"line":708},[144,8378,5005],{"class":257},[144,8380,858],{"class":261},[144,8382,8383,8386,8388],{"class":146,"line":714},[144,8384,8385],{"class":261},"            task ",[144,8387,265],{"class":257},[144,8389,8390],{"class":261}," generate_video_with_retry(payload)\n",[144,8392,8393,8395,8397,8399,8402,8404,8407,8409,8412,8414,8416,8418,8420,8422,8424],{"class":146,"line":720},[144,8394,5441],{"class":154},[144,8396,792],{"class":261},[144,8398,438],{"class":257},[144,8400,8401],{"class":158},"\"[",[144,8403,683],{"class":154},[144,8405,8406],{"class":261},"index",[144,8408,689],{"class":154},[144,8410,8411],{"class":158},"] Submitted: ",[144,8413,683],{"class":154},[144,8415,1529],{"class":261},[144,8417,1532],{"class":158},[144,8419,1535],{"class":261},[144,8421,689],{"class":154},[144,8423,447],{"class":158},[144,8425,404],{"class":261},[144,8427,8428,8431,8433,8435,8437],{"class":146,"line":726},[144,8429,8430],{"class":261},"            result ",[144,8432,265],{"class":257},[144,8434,1623],{"class":261},[144,8436,1626],{"class":158},[144,8438,1629],{"class":261},[144,8440,8441,8443,8445,8447,8449,8451,8453],{"class":146,"line":737},[144,8442,7261],{"class":261},[144,8444,265],{"class":257},[144,8446,1648],{"class":261},[144,8448,1651],{"class":158},[144,8450,1562],{"class":261},[144,8452,781],{"class":154},[144,8454,762],{"class":261},[144,8456,8457,8460,8462,8465,8467,8469,8471,8473],{"class":146,"line":742},[144,8458,8459],{"class":261},"            download_video(video_url, ",[144,8461,438],{"class":257},[144,8463,8464],{"class":158},"\"batch_",[144,8466,683],{"class":154},[144,8468,8406],{"class":261},[144,8470,689],{"class":154},[144,8472,6749],{"class":158},[144,8474,404],{"class":261},[144,8476,8477,8479],{"class":146,"line":748},[144,8478,864],{"class":257},[144,8480,8481],{"class":261}," (prompt, result)\n",[144,8483,8484,8486,8488,8490],{"class":146,"line":765},[144,8485,5404],{"class":257},[144,8487,6919],{"class":154},[144,8489,6922],{"class":257},[144,8491,5516],{"class":261},[144,8493,8494,8496,8498,8500,8502,8504,8506,8508,8511,8513,8515,8517,8519],{"class":146,"line":786},[144,8495,5441],{"class":154},[144,8497,792],{"class":261},[144,8499,438],{"class":257},[144,8501,8401],{"class":158},[144,8503,683],{"class":154},[144,8505,8406],{"class":261},[144,8507,689],{"class":154},[144,8509,8510],{"class":158},"] Failed: ",[144,8512,683],{"class":154},[144,8514,5560],{"class":261},[144,8516,689],{"class":154},[144,8518,447],{"class":158},[144,8520,404],{"class":261},[144,8522,8523,8525,8528,8531],{"class":146,"line":832},[144,8524,864],{"class":257},[144,8526,8527],{"class":261}," (prompt, ",[144,8529,8530],{"class":154},"str",[144,8532,8533],{"class":261},"(e))\n",[144,8535,8536],{"class":146,"line":837},[144,8537,561],{"class":261},[144,8539,8540],{"class":146,"line":843},[144,8541,8542],{"class":173},"    # レート制限を尊重してバッチで処理\n",[144,8544,8545,8547,8550,8553,8555,8558,8560],{"class":146,"line":861},[144,8546,1150],{"class":257},[144,8548,8549],{"class":261}," concurrent.futures.ThreadPoolExecutor(",[144,8551,8552],{"class":699},"max_workers",[144,8554,265],{"class":257},[144,8556,8557],{"class":261},"max_concurrent) ",[144,8559,1165],{"class":257},[144,8561,8562],{"class":261}," executor:\n",[144,8564,8565,8568,8570],{"class":146,"line":870},[144,8566,8567],{"class":261},"        futures ",[144,8569,265],{"class":257},[144,8571,426],{"class":261},[144,8573,8574],{"class":146,"line":885},[144,8575,8576],{"class":261},"            executor.submit(generate_one, prompt, i): i\n",[144,8578,8579,8581,8584,8586,8588],{"class":146,"line":901},[144,8580,6835],{"class":257},[144,8582,8583],{"class":261}," i, prompt ",[144,8585,1179],{"class":257},[144,8587,6149],{"class":154},[144,8589,8590],{"class":261},"(prompts)\n",[144,8592,8593],{"class":146,"line":913},[144,8594,8374],{"class":261},[144,8596,8597,8599,8602,8604],{"class":146,"line":952},[144,8598,1173],{"class":257},[144,8600,8601],{"class":261}," future ",[144,8603,1179],{"class":257},[144,8605,8606],{"class":261}," concurrent.futures.as_completed(futures):\n",[144,8608,8609],{"class":146,"line":958},[144,8610,8611],{"class":261},"            results.append(future.result())\n",[144,8613,8614],{"class":146,"line":963},[144,8615,561],{"class":261},[144,8617,8618],{"class":146,"line":969},[144,8619,8620],{"class":173},"    # サマリー\n",[144,8622,8623,8626,8628,8631,8633,8635,8637,8640,8642,8645,8647,8650,8653,8656],{"class":146,"line":975},[144,8624,8625],{"class":261},"    succeeded ",[144,8627,265],{"class":257},[144,8629,8630],{"class":154}," sum",[144,8632,792],{"class":261},[144,8634,5307],{"class":154},[144,8636,6252],{"class":257},[144,8638,8639],{"class":261}," _, r ",[144,8641,1179],{"class":257},[144,8643,8644],{"class":261}," results ",[144,8646,1719],{"class":257},[144,8648,8649],{"class":154}," isinstance",[144,8651,8652],{"class":261},"(r, ",[144,8654,8655],{"class":154},"dict",[144,8657,8658],{"class":261},"))\n",[144,8660,8661,8663,8665,8667,8669,8671,8674,8676,8679,8681,8683,8685,8688,8690,8693],{"class":146,"line":987},[144,8662,1101],{"class":154},[144,8664,792],{"class":261},[144,8666,438],{"class":257},[144,8668,447],{"class":158},[144,8670,1670],{"class":154},[144,8672,8673],{"class":158},"Batch complete: ",[144,8675,683],{"class":154},[144,8677,8678],{"class":261},"succeeded",[144,8680,689],{"class":154},[144,8682,1225],{"class":158},[144,8684,6128],{"class":154},[144,8686,8687],{"class":261},"(prompts)",[144,8689,689],{"class":154},[144,8691,8692],{"class":158}," succeeded\"",[144,8694,404],{"class":261},[144,8696,8697,8699],{"class":146,"line":992},[144,8698,1703],{"class":257},[144,8700,8701],{"class":261}," results\n",[144,8703,8704],{"class":146,"line":5401},[144,8705,374],{"emptyLinePlaceholder":57},[144,8707,8708],{"class":146,"line":5410},[144,8709,374],{"emptyLinePlaceholder":57},[144,8711,8712],{"class":146,"line":5438},[144,8713,8714],{"class":173},"# 使用例\n",[144,8716,8717,8720,8722],{"class":146,"line":5469},[144,8718,8719],{"class":261},"prompts ",[144,8721,265],{"class":257},[144,8723,8724],{"class":261}," [\n",[144,8726,8727,8730],{"class":146,"line":5489},[144,8728,8729],{"class":158},"    \"A hummingbird hovering near a red flower. Macro lens, shallow depth of field.\"",[144,8731,450],{"class":261},[144,8733,8734,8737],{"class":146,"line":5495},[144,8735,8736],{"class":158},"    \"Ocean waves crashing on volcanic rocks at sunset. Slow motion.\"",[144,8738,450],{"class":261},[144,8740,8741,8744],{"class":146,"line":5501},[144,8742,8743],{"class":158},"    \"A street musician playing violin in the rain. Cinematic lighting.\"",[144,8745,450],{"class":261},[144,8747,8748],{"class":146,"line":5506},[144,8749,762],{"class":261},[144,8751,8752,8755,8758,8760,8762],{"class":146,"line":5519},[144,8753,8754],{"class":261},"batch_generate(prompts, ",[144,8756,8757],{"class":699},"max_concurrent",[144,8759,265],{"class":257},[144,8761,5288],{"class":154},[144,8763,404],{"class":261},[10,8765,8766],{},"バッチ処理の主な考慮事項：",[95,8768,8769,8777,8783],{},[72,8770,8771,8776],{},[22,8772,8773],{},[27,8774,8775],{},"max_concurrent=3"," — 同時に送信するリクエストが多すぎないようにしてください。2〜3 から始めて、レート制限に応じて増やしてください。",[72,8778,8779,8782],{},[22,8780,8781],{},"ThreadPoolExecutor"," — I/O バウンド（API レスポンス待ち）であり CPU バウンドではないため、プロセスではなくスレッドを使用します。",[72,8784,8785,8788],{},[22,8786,8787],{},"エラー分離"," — 各動画生成は独立しています。1 つの失敗がバッチ全体を止めることはありません。",[44,8790],{},[47,8792,8793],{"id":8793},"次のステップ",[10,8795,8796],{},"基本をすべてカバーしました — テキストから動画、画像から動画、非同期 polling、webhook、エラー処理、バッチ処理。さらに深掘りするためのリソースを紹介します：",[91,8798,8799],{"id":8799},"高度な機能を探索",[95,8801,8802,8810,8817,8824,8832],{},[72,8803,8804,8809],{},[22,8805,8806],{},[36,8807,8808],{"href":2966},"@Tags マルチモーダル参照ガイド"," — @Image、@Video、@Audio 参照システムをマスターしてマルチモーダル生成",[72,8811,8812,8816],{},[22,8813,8814],{},[36,8815,3855],{"href":3854}," — ヒッチコックズーム、ワンテイクトラッキングショット、オービタルカメラをプログラムで実装",[72,8818,8819,8823],{},[22,8820,8821],{},[36,8822,3381],{"href":3380}," — 最初/最後のフレーム制御、マルチ画像合成、EC 商品動画",[72,8825,8826,8831],{},[22,8827,8828],{},[36,8829,8830],{"href":2612},"EC 商品動画ガイド"," — 商品写真を大規模にマーケティング動画に変換",[72,8833,8834,8838],{},[22,8835,8836],{},[36,8837,1767],{"href":1766}," — ショットスクリプト形式、タイミング構文、デモ動画のプロンプト",[91,8840,8841],{"id":8841},"リファレンスドキュメント",[95,8843,8844,8850,8857],{},[72,8845,8846],{},[36,8847,8849],{"href":1257,"rel":8848},[40],"動画生成 API リファレンス",[72,8851,8852],{},[36,8853,8856],{"href":8854,"rel":8855},"https://seedance2api.app/docs/multimodal-reference",[40],"マルチモーダル参照仕様",[72,8858,8859],{},[36,8860,8863],{"href":8861,"rel":8862},"https://seedance2api.app/docs/sdks",[40],"Python & Node.js SDK",[91,8865,8866],{"id":8866},"何か作ってみよう",[10,8868,8869],{},"学んだことを組み合わせてみましょう。プロジェクトのアイデア：",[95,8871,8872,8882,8888,8898],{},[72,8873,8874,8877,8878,8881],{},[22,8875,8876],{},"自動化された商品動画パイプライン"," — 商品写真をアップロードし、マーケティング動画を大量生成（",[36,8879,8880],{"href":2612},"EC 動画ガイド","参照）",[72,8883,8884,8887],{},[22,8885,8886],{},"ソーシャルメディアコンテンツエンジン"," — テキストブリーフから縦型ショート動画を生成し、TikTok/Reels に直接投稿",[72,8889,8890,8893,8894,8897],{},[22,8891,8892],{},"ストーリーボードから動画ツール"," — 連続画像を",[36,8895,8896],{"href":3854},"カメラムーブメント制御","付きのアニメーションシーンに変換",[72,8899,8900,8903],{},[22,8901,8902],{},"AI 動画編集パイプライン"," — Seedance 2.0 の動画拡張機能を活用して、短いクリップからより長いストーリーを構成",[10,8905,8906],{},[22,8907,8908,8909,8913],{},"準備はできましたか？",[36,8910,8912],{"href":38,"rel":8911},[40],"無料 EvoLink API Key を取得","して、今日から動画を生成しましょう。",[44,8915],{},[47,8917,8918],{"id":8918},"よくある質問",[91,8920,8922],{"id":8921},"seedance-20-の動画生成にはどのくらい時間がかかりますか","Seedance 2.0 の動画生成にはどのくらい時間がかかりますか？",[10,8924,8925,8926,8928],{},"通常、長さと品質設定に応じて 30〜120 秒です。5 秒 720p の動画は約 50 秒で完了します。15 秒 1080p の動画は 2〜3 分かかることがあります。API は各タスクに ",[27,8927,2107],{}," フィールドを返すので、適切なタイムアウトを設定できます。ピーク時にはキュー待ち時間が 10〜30 秒追加される場合があります。",[91,8930,8932],{"id":8931},"seedance-20-api-はどの画像フォーマットに対応していますか","Seedance 2.0 API はどの画像フォーマットに対応していますか？",[10,8934,8935,8936,8938],{},"JPEG、PNG、WebP、BMP、TIFF、GIF。各画像は 30 MB 以下である必要があります。",[27,8937,2895],{}," パラメータでリクエストあたり最大 9 枚の画像を渡せます。画像は公開アクセス可能な URL である必要があります — API が直接取得します。最良の結果を得るには、短辺が 720px 以上の画像を使用してください。非常に低解像度の画像（256px 未満）はぼやけたアニメーションになる可能性があります。",[91,8940,8942],{"id":8941},"_15-秒より長い動画を生成できますか","15 秒より長い動画を生成できますか？",[10,8944,8945,8946,8948],{},"単一生成の最大は 15 秒です。より長いコンテンツを作るには、複数のクリップを生成して FFmpeg や動画エディタで結合してください。Seedance 2.0 は動画拡張をサポートしています — 生成した動画の最後のフレームを次の生成の最初のフレームとして使用し、シームレスな連続性を実現できます。基本的なアプローチ：クリップ 1 を生成し、最後のフレームを抽出して、クリップ 2 に ",[27,8947,2994],{}," として渡します。",[91,8950,8952],{"id":8951},"evolink-経由の-seedance-20-api-の料金はいくらですか","EvoLink 経由の Seedance 2.0 API の料金はいくらですか？",[10,8954,8955,8956,8960,8961,8963],{},"料金は動画の長さと品質ティアに基づきます。5 秒 720p の動画は約 18 クレジットです。EvoLink は直接 API アクセスと比較してコストを削減できる",[36,8957,8959],{"href":210,"rel":8958},[40],"スマートルーティング","を提供しています。現在の秒単位の料金はダッシュボードで確認してください。API レスポンスの ",[27,8962,2117],{}," フィールドが生成前に正確なコストを表示します — この金額以上に課金されることはありません。",[91,8965,8967],{"id":8966},"seedance-15-pro-と-seedance-20-の違いは何ですか","seedance-1.5-pro と seedance-2.0 の違いは何ですか？",[10,8969,8970,8971,8973,8974,8976,8977,1768],{},"Seedance 2.0 はマルチモーダル参照（画像・動画・音声の混合入力）、ネイティブオーディオ生成、物理的一貫性の向上、動画編集機能を追加しています。API インターフェースは同一です — 同じエンドポイント、同じパラメータ、同じレスポンス形式。今 ",[27,8972,29],{}," でテストし、モデル名を変更するだけで ",[27,8975,1751],{}," に切り替えられます。1.5 の主な制限：単一画像入力のみ（@Image2〜9 不可）、動画/音声参照不可、ネイティブオーディオ生成不可。詳細な比較は ",[36,8978,8980],{"href":8979},"/blog/seedance-2-vs-sora-2-api-comparison","Seedance 2.0 vs Sora 2 比較",[91,8982,8984],{"id":8983},"content-rejected-by-safety-filterエラーはどう対処しますか","「content rejected by safety filter」エラーはどう対処しますか？",[10,8986,8987,8988,8990,8991,8994],{},"コンテンツ審査システムはリアルな暴力、露骨なコンテンツ、実在の公人を含むプロンプトを拒否します。",[27,8989,2895],{}," 経由でアップロードされたリアルな人物の顔画像も拒否されます。顔の制限を回避するには、イラスト、スタイライズされた、またはアニメスタイルのキャラクター画像を使用してください。プロンプト拒否の場合は、制限されたトピックを避けるよう文言を修正してください。エラーレスポンスに ",[27,8992,8993],{},"type: \"content_policy_violation\""," が含まれます — エラー処理コードでこれをチェックし、ユーザーに明確なメッセージを提供してください。",[91,8996,8998],{"id":8997},"nodejs-javascript-プロジェクトで-seedance-api-を使えますか","Node.js / JavaScript プロジェクトで Seedance API を使えますか？",[10,9000,9001,9002,279,9005,9008,9009,9013],{},"はい。REST API は言語に依存しません — どの HTTP クライアントでも使えます。このチュートリアルの概念（非同期 polling、webhook、エラー処理）は Node.js の ",[27,9003,9004],{},"fetch",[27,9006,9007],{},"axios"," で直接適用できます。EvoLink は polling とリトライを自動処理する公式 ",[36,9010,9012],{"href":8861,"rel":9011},[40],"Node.js および Python SDK"," も提供しています。",[91,9015,9017],{"id":9016},"動画完了時に-webhook-サーバーがダウンしていたらどうなりますか","動画完了時に webhook サーバーがダウンしていたらどうなりますか？",[10,9019,9020,9021,9024],{},"API は増加する間隔（1 秒、2 秒、4 秒）で webhook 配信を 3 回リトライします。3 回すべて失敗すると webhook は放棄されます — ただし動画は引き続き利用可能です。",[27,9022,9023],{},"GET /v1/tasks/{task_id}"," で polling して結果を取得できます。そのため、送信時にタスク ID を保存し、完了したが webhook で受信されなかったタスクを定期的にチェックするバックグラウンドジョブを設定するのがベストプラクティスです。",[91,9026,9028],{"id":9027},"api-リクエストにレート制限はありますか","API リクエストにレート制限はありますか？",[10,9030,9031,9032,9034,9035,9039,9040,9044],{},"はい。デフォルトのレート制限は開発と中規模のプロダクション使用には十分余裕があります。",[27,9033,4809],{}," エラーが発生した場合は、",[36,9036,9038],{"href":9037},"#%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E9%81%A9%E5%88%87%E3%81%AB%E5%87%A6%E7%90%86%E3%81%99%E3%82%8B","エラー処理セクション","で示した指数バックオフを実装してください。大規模な使用ケース（1 日数千本の動画）の場合は、",[36,9041,9043],{"href":210,"rel":9042},[40],"EvoLink サポート","に連絡してカスタムレート制限と専用キャパシティについて相談してください。",[91,9046,9048],{"id":9047},"seedance-20-を商用プロジェクトに使えますか","Seedance 2.0 を商用プロジェクトに使えますか？",[10,9050,9051,9052,1768],{},"はい。EvoLink API を通じて生成された動画は商用利用が許可されています。出力の所有権はユーザーにあり、製品、マーケティング資料、クライアント納品物、公開コンテンツに使用できます。詳細なライセンス条件と商用利用のベストプラクティスは ",[36,9053,9055],{"href":9054},"/blog/seedance-2-copyright-api-guide","Seedance 2.0 著作権ガイド",[44,9057],{},[47,9059,9060],{"id":9060},"完全なスクリプト",[10,9062,9063],{},"このチュートリアルの全コードを 1 つのファイルにまとめました — コピー、ペースト、API Key を入力して、すぐに実行できます：",[135,9065,9067],{"className":336,"code":9066,"language":338,"meta":140,"style":140},"\"\"\"\nSeedance 2.0 API チュートリアル — 完全スクリプト\nドキュメント：https://seedance2api.app/docs/video-generation\nAPI Key：https://evolink.ai/early-access\n\"\"\"\nimport requests\nimport time\nimport os\nimport json\nimport random\n\n# ── 設定 ─────────────────────────────────────────────────────\nAPI_KEY = os.getenv(\"EVOLINK_API_KEY\", \"sk-your-api-key-here\")\nBASE_URL = \"https://api.evolink.ai/v1\"\nHEADERS = {\n    \"Authorization\": f\"Bearer {API_KEY}\",\n    \"Content-Type\": \"application/json\"\n}\n\n\n# ── 再利用可能なヘルパー ──────────────────────────────────────\ndef wait_for_video(task_id, poll_interval=10, timeout=600):\n    \"\"\"動画生成タスクを完了まで polling します。\"\"\"\n    elapsed = 0\n    while elapsed \u003C timeout:\n        response = requests.get(\n            f\"{BASE_URL}/tasks/{task_id}\",\n            headers=HEADERS\n        )\n        response.raise_for_status()\n        task = response.json()\n        status = task[\"status\"]\n        progress = task.get(\"progress\", 0)\n        print(f\"  [{elapsed}s] Status: {status} | Progress: {progress}%\")\n        if status == \"completed\":\n            return task\n        elif status == \"failed\":\n            raise RuntimeError(f\"Task {task_id} failed: {task}\")\n        time.sleep(poll_interval)\n        elapsed += poll_interval\n    raise TimeoutError(f\"Task {task_id} timed out after {timeout}s\")\n\n\ndef download_video(url, filename=\"output.mp4\"):\n    \"\"\"URL から動画ファイルをダウンロードします。\"\"\"\n    print(f\"Downloading to {filename}...\")\n    resp = requests.get(url, stream=True)\n    resp.raise_for_status()\n    with open(filename, \"wb\") as f:\n        for chunk in resp.iter_content(chunk_size=8192):\n            f.write(chunk)\n    print(f\"Saved: {filename} ({os.path.getsize(filename) / 1024:.0f} KB)\")\n\n\ndef generate_video_with_retry(payload, max_retries=3):\n    \"\"\"一時的なエラーに対して自動リトライする生成リクエスト送信。\"\"\"\n    for attempt in range(max_retries):\n        try:\n            response = requests.post(\n                f\"{BASE_URL}/videos/generations\",\n                headers=HEADERS,\n                json=payload,\n                timeout=30\n            )\n            if response.status_code == 200:\n                return response.json()\n            error = response.json().get(\"error\", {})\n            if response.status_code in (400, 401, 402, 404, 413, 422):\n                raise ValueError(\n                    f\"API error {response.status_code}: \"\n                    f\"{error.get('message', 'Unknown')}\"\n                )\n            if response.status_code in (429, 500, 502, 503):\n                wait = (2 ** attempt) + random.uniform(0, 1)\n                print(f\"  Retry {attempt+1}/{max_retries} after {wait:.1f}s\")\n                time.sleep(wait)\n                continue\n        except requests.exceptions.RequestException:\n            wait = (2 ** attempt) + random.uniform(0, 1)\n            print(f\"  Retry {attempt+1}/{max_retries} after {wait:.1f}s\")\n            time.sleep(wait)\n            continue\n    raise RuntimeError(f\"Failed after {max_retries} retries\")\n\n\ndef validate_payload(payload):\n    \"\"\"API コール前に生成 payload をバリデーションします。\"\"\"\n    errors = []\n    if not payload.get(\"model\"):\n        errors.append(\"'model' is required\")\n    if not payload.get(\"prompt\") or not payload[\"prompt\"].strip():\n        errors.append(\"'prompt' is required\")\n    duration = payload.get(\"duration\", 5)\n    if duration \u003C 4 or duration > 15:\n        errors.append(f\"'duration' must be 4-15, got {duration}\")\n    quality = payload.get(\"quality\", \"720p\")\n    if quality not in {\"480p\", \"720p\", \"1080p\"}:\n        errors.append(f\"Invalid quality: {quality}\")\n    if errors:\n        raise ValueError(\"Validation failed:\\n\" + \"\\n\".join(f\"  - {e}\" for e in errors))\n\n\ndef cancel_task(task_id):\n    \"\"\"pending または processing 状態のタスクをキャンセルします。\"\"\"\n    response = requests.post(\n        f\"{BASE_URL}/tasks/{task_id}/cancel\",\n        headers=HEADERS\n    )\n    if response.status_code == 200:\n        print(f\"Task {task_id} cancelled.\")\n    else:\n        print(f\"Cancel failed: {response.json()}\")\n\n\n# ── 例 1：テキストから動画 ────────────────────────────────────\ndef text_to_video():\n    payload = {\n        \"model\": \"seedance-2.0\",\n        \"prompt\": (\n            \"A golden retriever puppy chases a butterfly through \"\n            \"a sunlit meadow. The camera follows the puppy with a \"\n            \"smooth tracking shot as wildflowers sway in the breeze.\"\n        ),\n        \"duration\": 5,\n        \"quality\": \"720p\",\n        \"aspect_ratio\": \"16:9\",\n        \"generate_audio\": True\n    }\n    validate_payload(payload)\n    task = generate_video_with_retry(payload)\n    print(f\"Task: {task['id']} (ETA: {task['task_info']['estimated_time']}s)\")\n    result = wait_for_video(task[\"id\"])\n    download_video(result[\"results\"][0], \"text_to_video.mp4\")\n\n\n# ── 例 2：画像から動画 ────────────────────────────────────────\ndef image_to_video():\n    payload = {\n        \"model\": \"seedance-2.0\",\n        \"prompt\": (\n            \"@Image1 as the first frame. The scene slowly comes \"\n            \"to life — leaves rustle gently, soft light shifts \"\n            \"across the frame.\"\n        ),\n        \"image_urls\": [\"https://example.com/your-image.jpg\"],\n        \"duration\": 5,\n        \"quality\": \"720p\"\n    }\n    validate_payload(payload)\n    task = generate_video_with_retry(payload)\n    print(f\"Task: {task['id']}\")\n    result = wait_for_video(task[\"id\"])\n    download_video(result[\"results\"][0], \"image_to_video.mp4\")\n\n\n# ── 例 3：縦型ソーシャルメディア動画 ──────────────────────────\ndef social_media_video():\n    payload = {\n        \"model\": \"seedance-2.0\",\n        \"prompt\": (\n            \"A barista pours latte art in slow motion. \"\n            \"Close-up overhead shot, warm cafe lighting.\"\n        ),\n        \"duration\": 8,\n        \"quality\": \"1080p\",\n        \"aspect_ratio\": \"9:16\",\n        \"generate_audio\": True\n    }\n    validate_payload(payload)\n    task = generate_video_with_retry(payload)\n    print(f\"Task: {task['id']}\")\n    result = wait_for_video(task[\"id\"])\n    download_video(result[\"results\"][0], \"social_video.mp4\")\n\n\nif __name__ == \"__main__\":\n    print(\"=== テキストから動画 ===\")\n    text_to_video()\n    # print(\"\\n=== 画像から動画 ===\")\n    # image_to_video()  # コメントを外して画像 URL を設定\n    # print(\"\\n=== ソーシャルメディア動画 ===\")\n    # social_media_video()\n",[27,9068,9069,9073,9078,9083,9088,9092,9098,9104,9110,9116,9122,9126,9130,9146,9154,9162,9178,9186,9190,9194,9198,9203,9223,9228,9236,9246,9254,9274,9282,9286,9290,9298,9310,9326,9362,9374,9380,9392,9423,9427,9435,9465,9469,9473,9487,9491,9512,9528,9532,9548,9566,9570,9604,9608,9612,9626,9631,9643,9649,9657,9669,9679,9687,9696,9700,9712,9718,9730,9764,9772,9787,9811,9815,9841,9867,9910,9914,9918,9925,9951,9991,9995,9999,10021,10025,10029,10037,10042,10050,10062,10070,10092,10101,10117,10137,10155,10171,10196,10215,10222,10268,10273,10278,10287,10293,10302,10323,10332,10337,10350,10372,10379,10400,10405,10410,10416,10425,10434,10445,10452,10457,10462,10467,10472,10483,10494,10505,10514,10519,10525,10534,10578,10591,10611,10616,10621,10627,10636,10645,10656,10663,10668,10673,10679,10684,10698,10709,10718,10723,10728,10737,10762,10775,10793,10798,10803,10809,10819,10828,10839,10846,10852,10858,10863,10874,10885,10896,10905,10910,10915,10924,10949,10962,10980,10985,10990,11003,11015,11020,11026,11032,11038],{"__ignoreMap":140},[144,9070,9071],{"class":146,"line":147},[144,9072,6561],{"class":158},[144,9074,9075],{"class":146,"line":165},[144,9076,9077],{"class":158},"Seedance 2.0 API チュートリアル — 完全スクリプト\n",[144,9079,9080],{"class":146,"line":177},[144,9081,9082],{"class":158},"ドキュメント：https://seedance2api.app/docs/video-generation\n",[144,9084,9085],{"class":146,"line":186},[144,9086,9087],{"class":158},"API Key：https://evolink.ai/early-access\n",[144,9089,9090],{"class":146,"line":371},[144,9091,6561],{"class":158},[144,9093,9094,9096],{"class":146,"line":377},[144,9095,345],{"class":257},[144,9097,327],{"class":261},[144,9099,9100,9102],{"class":146,"line":383},[144,9101,345],{"class":257},[144,9103,354],{"class":261},[144,9105,9106,9108],{"class":146,"line":407},[144,9107,345],{"class":257},[144,9109,361],{"class":261},[144,9111,9112,9114],{"class":146,"line":418},[144,9113,345],{"class":257},[144,9115,368],{"class":261},[144,9117,9118,9120],{"class":146,"line":429},[144,9119,345],{"class":257},[144,9121,4907],{"class":261},[144,9123,9124],{"class":146,"line":453},[144,9125,374],{"emptyLinePlaceholder":57},[144,9127,9128],{"class":146,"line":464},[144,9129,380],{"class":173},[144,9131,9132,9134,9136,9138,9140,9142,9144],{"class":146,"line":598},[144,9133,386],{"class":154},[144,9135,389],{"class":257},[144,9137,392],{"class":261},[144,9139,395],{"class":158},[144,9141,398],{"class":261},[144,9143,401],{"class":158},[144,9145,404],{"class":261},[144,9147,9148,9150,9152],{"class":146,"line":603},[144,9149,410],{"class":154},[144,9151,389],{"class":257},[144,9153,415],{"class":158},[144,9155,9156,9158,9160],{"class":146,"line":609},[144,9157,421],{"class":154},[144,9159,389],{"class":257},[144,9161,426],{"class":261},[144,9163,9164,9166,9168,9170,9172,9174,9176],{"class":146,"line":615},[144,9165,432],{"class":158},[144,9167,435],{"class":261},[144,9169,438],{"class":257},[144,9171,441],{"class":158},[144,9173,444],{"class":154},[144,9175,447],{"class":158},[144,9177,450],{"class":261},[144,9179,9180,9182,9184],{"class":146,"line":621},[144,9181,456],{"class":158},[144,9183,435],{"class":261},[144,9185,461],{"class":158},[144,9187,9188],{"class":146,"line":626},[144,9189,467],{"class":261},[144,9191,9192],{"class":146,"line":637},[144,9193,374],{"emptyLinePlaceholder":57},[144,9195,9196],{"class":146,"line":652},[144,9197,374],{"emptyLinePlaceholder":57},[144,9199,9200],{"class":146,"line":658},[144,9201,9202],{"class":173},"# ── 再利用可能なヘルパー ──────────────────────────────────────\n",[144,9204,9205,9207,9209,9211,9213,9215,9217,9219,9221],{"class":146,"line":669},[144,9206,524],{"class":257},[144,9208,527],{"class":150},[144,9210,530],{"class":261},[144,9212,265],{"class":257},[144,9214,535],{"class":154},[144,9216,538],{"class":261},[144,9218,265],{"class":257},[144,9220,543],{"class":154},[144,9222,546],{"class":261},[144,9224,9225],{"class":146,"line":696},[144,9226,9227],{"class":158},"    \"\"\"動画生成タスクを完了まで polling します。\"\"\"\n",[144,9229,9230,9232,9234],{"class":146,"line":708},[144,9231,629],{"class":261},[144,9233,265],{"class":257},[144,9235,634],{"class":154},[144,9237,9238,9240,9242,9244],{"class":146,"line":714},[144,9239,640],{"class":257},[144,9241,643],{"class":261},[144,9243,646],{"class":257},[144,9245,649],{"class":261},[144,9247,9248,9250,9252],{"class":146,"line":720},[144,9249,661],{"class":261},[144,9251,265],{"class":257},[144,9253,666],{"class":261},[144,9255,9256,9258,9260,9262,9264,9266,9268,9270,9272],{"class":146,"line":726},[144,9257,672],{"class":257},[144,9259,447],{"class":158},[144,9261,677],{"class":154},[144,9263,680],{"class":158},[144,9265,683],{"class":154},[144,9267,686],{"class":261},[144,9269,689],{"class":154},[144,9271,447],{"class":158},[144,9273,450],{"class":261},[144,9275,9276,9278,9280],{"class":146,"line":737},[144,9277,700],{"class":699},[144,9279,265],{"class":257},[144,9281,705],{"class":154},[144,9283,9284],{"class":146,"line":742},[144,9285,711],{"class":261},[144,9287,9288],{"class":146,"line":748},[144,9289,723],{"class":261},[144,9291,9292,9294,9296],{"class":146,"line":765},[144,9293,729],{"class":261},[144,9295,265],{"class":257},[144,9297,734],{"class":261},[144,9299,9300,9302,9304,9306,9308],{"class":146,"line":786},[144,9301,751],{"class":261},[144,9303,265],{"class":257},[144,9305,756],{"class":261},[144,9307,759],{"class":158},[144,9309,762],{"class":261},[144,9311,9312,9314,9316,9318,9320,9322,9324],{"class":146,"line":832},[144,9313,768],{"class":261},[144,9315,265],{"class":257},[144,9317,773],{"class":261},[144,9319,776],{"class":158},[144,9321,398],{"class":261},[144,9323,781],{"class":154},[144,9325,404],{"class":261},[144,9327,9328,9330,9332,9334,9336,9338,9340,9342,9344,9346,9348,9350,9352,9354,9356,9358,9360],{"class":146,"line":837},[144,9329,789],{"class":154},[144,9331,792],{"class":261},[144,9333,438],{"class":257},[144,9335,797],{"class":158},[144,9337,683],{"class":154},[144,9339,802],{"class":261},[144,9341,689],{"class":154},[144,9343,807],{"class":158},[144,9345,683],{"class":154},[144,9347,812],{"class":261},[144,9349,689],{"class":154},[144,9351,817],{"class":158},[144,9353,683],{"class":154},[144,9355,822],{"class":261},[144,9357,689],{"class":154},[144,9359,827],{"class":158},[144,9361,404],{"class":261},[144,9363,9364,9366,9368,9370,9372],{"class":146,"line":843},[144,9365,846],{"class":257},[144,9367,849],{"class":261},[144,9369,852],{"class":257},[144,9371,855],{"class":158},[144,9373,858],{"class":261},[144,9375,9376,9378],{"class":146,"line":861},[144,9377,864],{"class":257},[144,9379,867],{"class":261},[144,9381,9382,9384,9386,9388,9390],{"class":146,"line":870},[144,9383,873],{"class":257},[144,9385,849],{"class":261},[144,9387,852],{"class":257},[144,9389,880],{"class":158},[144,9391,858],{"class":261},[144,9393,9394,9396,9398,9400,9402,9404,9406,9408,9410,9412,9414,9417,9419,9421],{"class":146,"line":885},[144,9395,904],{"class":257},[144,9397,907],{"class":154},[144,9399,792],{"class":261},[144,9401,438],{"class":257},[144,9403,919],{"class":158},[144,9405,683],{"class":154},[144,9407,686],{"class":261},[144,9409,689],{"class":154},[144,9411,928],{"class":158},[144,9413,683],{"class":154},[144,9415,9416],{"class":261},"task",[144,9418,689],{"class":154},[144,9420,447],{"class":158},[144,9422,404],{"class":261},[144,9424,9425],{"class":146,"line":901},[144,9426,972],{"class":261},[144,9428,9429,9431,9433],{"class":146,"line":913},[144,9430,978],{"class":261},[144,9432,981],{"class":257},[144,9434,984],{"class":261},[144,9436,9437,9439,9441,9443,9445,9447,9449,9451,9453,9455,9457,9459,9461,9463],{"class":146,"line":952},[144,9438,995],{"class":257},[144,9440,998],{"class":154},[144,9442,792],{"class":261},[144,9444,438],{"class":257},[144,9446,919],{"class":158},[144,9448,683],{"class":154},[144,9450,686],{"class":261},[144,9452,689],{"class":154},[144,9454,1013],{"class":158},[144,9456,683],{"class":154},[144,9458,1018],{"class":261},[144,9460,689],{"class":154},[144,9462,1023],{"class":158},[144,9464,404],{"class":261},[144,9466,9467],{"class":146,"line":958},[144,9468,374],{"emptyLinePlaceholder":57},[144,9470,9471],{"class":146,"line":963},[144,9472,374],{"emptyLinePlaceholder":57},[144,9474,9475,9477,9479,9481,9483,9485],{"class":146,"line":969},[144,9476,524],{"class":257},[144,9478,1081],{"class":150},[144,9480,1084],{"class":261},[144,9482,265],{"class":257},[144,9484,1089],{"class":158},[144,9486,546],{"class":261},[144,9488,9489],{"class":146,"line":975},[144,9490,1096],{"class":158},[144,9492,9493,9495,9497,9499,9502,9504,9506,9508,9510],{"class":146,"line":987},[144,9494,1101],{"class":154},[144,9496,792],{"class":261},[144,9498,438],{"class":257},[144,9500,9501],{"class":158},"\"Downloading to ",[144,9503,683],{"class":154},[144,9505,1113],{"class":261},[144,9507,689],{"class":154},[144,9509,1118],{"class":158},[144,9511,404],{"class":261},[144,9513,9514,9516,9518,9520,9522,9524,9526],{"class":146,"line":992},[144,9515,1125],{"class":261},[144,9517,265],{"class":257},[144,9519,1130],{"class":261},[144,9521,1133],{"class":699},[144,9523,265],{"class":257},[144,9525,1138],{"class":154},[144,9527,404],{"class":261},[144,9529,9530],{"class":146,"line":5401},[144,9531,1145],{"class":261},[144,9533,9534,9536,9538,9540,9542,9544,9546],{"class":146,"line":5410},[144,9535,1150],{"class":257},[144,9537,1153],{"class":154},[144,9539,1156],{"class":261},[144,9541,1159],{"class":158},[144,9543,1162],{"class":261},[144,9545,1165],{"class":257},[144,9547,1168],{"class":261},[144,9549,9550,9552,9554,9556,9558,9560,9562,9564],{"class":146,"line":5438},[144,9551,1173],{"class":257},[144,9553,1176],{"class":261},[144,9555,1179],{"class":257},[144,9557,1182],{"class":261},[144,9559,1185],{"class":699},[144,9561,265],{"class":257},[144,9563,1190],{"class":154},[144,9565,546],{"class":261},[144,9567,9568],{"class":146,"line":5469},[144,9569,1197],{"class":261},[144,9571,9572,9574,9576,9578,9580,9582,9584,9586,9588,9590,9592,9594,9596,9598,9600,9602],{"class":146,"line":5489},[144,9573,1101],{"class":154},[144,9575,792],{"class":261},[144,9577,438],{"class":257},[144,9579,1208],{"class":158},[144,9581,683],{"class":154},[144,9583,1113],{"class":261},[144,9585,689],{"class":154},[144,9587,1217],{"class":158},[144,9589,683],{"class":154},[144,9591,1222],{"class":261},[144,9593,1225],{"class":257},[144,9595,1228],{"class":154},[144,9597,1231],{"class":257},[144,9599,689],{"class":154},[144,9601,1236],{"class":158},[144,9603,404],{"class":261},[144,9605,9606],{"class":146,"line":5495},[144,9607,374],{"emptyLinePlaceholder":57},[144,9609,9610],{"class":146,"line":5501},[144,9611,374],{"emptyLinePlaceholder":57},[144,9613,9614,9616,9618,9620,9622,9624],{"class":146,"line":5506},[144,9615,524],{"class":257},[144,9617,4918],{"class":150},[144,9619,4921],{"class":261},[144,9621,265],{"class":257},[144,9623,4926],{"class":154},[144,9625,546],{"class":261},[144,9627,9628],{"class":146,"line":5519},[144,9629,9630],{"class":158},"    \"\"\"一時的なエラーに対して自動リトライする生成リクエスト送信。\"\"\"\n",[144,9632,9633,9635,9637,9639,9641],{"class":146,"line":5546},[144,9634,4989],{"class":257},[144,9636,4992],{"class":261},[144,9638,1179],{"class":257},[144,9640,4997],{"class":154},[144,9642,5000],{"class":261},[144,9644,9645,9647],{"class":146,"line":5586},[144,9646,5005],{"class":257},[144,9648,858],{"class":261},[144,9650,9651,9653,9655],{"class":146,"line":5605},[144,9652,5012],{"class":261},[144,9654,265],{"class":257},[144,9656,1432],{"class":261},[144,9658,9659,9661,9663,9665,9667],{"class":146,"line":5610},[144,9660,916],{"class":257},[144,9662,447],{"class":158},[144,9664,677],{"class":154},[144,9666,1444],{"class":158},[144,9668,450],{"class":261},[144,9670,9671,9673,9675,9677],{"class":146,"line":5615},[144,9672,5033],{"class":699},[144,9674,265],{"class":257},[144,9676,421],{"class":154},[144,9678,450],{"class":261},[144,9680,9681,9683,9685],{"class":146,"line":5620},[144,9682,5044],{"class":699},[144,9684,265],{"class":257},[144,9686,5049],{"class":261},[144,9688,9689,9691,9693],{"class":146,"line":7273},[144,9690,5054],{"class":699},[144,9692,265],{"class":257},[144,9694,9695],{"class":154},"30\n",[144,9697,9698],{"class":146,"line":7295},[144,9699,955],{"class":261},[144,9701,9702,9704,9706,9708,9710],{"class":146,"line":7301},[144,9703,5080],{"class":257},[144,9705,2507],{"class":261},[144,9707,852],{"class":257},[144,9709,2512],{"class":154},[144,9711,858],{"class":261},[144,9713,9714,9716],{"class":146,"line":7307},[144,9715,5093],{"class":257},[144,9717,734],{"class":261},[144,9719,9720,9722,9724,9726,9728],{"class":146,"line":7318},[144,9721,5109],{"class":261},[144,9723,265],{"class":257},[144,9725,5114],{"class":261},[144,9727,895],{"class":158},[144,9729,898],{"class":261},[144,9731,9732,9734,9736,9738,9740,9742,9744,9746,9748,9750,9752,9754,9756,9758,9760,9762],{"class":146,"line":7329},[144,9733,5080],{"class":257},[144,9735,2507],{"class":261},[144,9737,1179],{"class":257},[144,9739,1217],{"class":261},[144,9741,3636],{"class":154},[144,9743,398],{"class":261},[144,9745,4719],{"class":154},[144,9747,398],{"class":261},[144,9749,4737],{"class":154},[144,9751,398],{"class":261},[144,9753,4755],{"class":154},[144,9755,398],{"class":261},[144,9757,4773],{"class":154},[144,9759,398],{"class":261},[144,9761,4791],{"class":154},[144,9763,546],{"class":261},[144,9765,9766,9768,9770],{"class":146,"line":7340},[144,9767,5205],{"class":257},[144,9769,5208],{"class":154},[144,9771,910],{"class":261},[144,9773,9774,9776,9778,9780,9782,9784],{"class":146,"line":7345},[144,9775,5215],{"class":257},[144,9777,5218],{"class":158},[144,9779,683],{"class":154},[144,9781,5223],{"class":261},[144,9783,689],{"class":154},[144,9785,9786],{"class":158},": \"\n",[144,9788,9789,9791,9793,9795,9798,9800,9802,9805,9807,9809],{"class":146,"line":7351},[144,9790,5215],{"class":257},[144,9792,447],{"class":158},[144,9794,683],{"class":154},[144,9796,9797],{"class":261},"error.get(",[144,9799,936],{"class":158},[144,9801,398],{"class":261},[144,9803,9804],{"class":158},"'Unknown'",[144,9806,944],{"class":261},[144,9808,689],{"class":154},[144,9810,949],{"class":158},[144,9812,9813],{"class":146,"line":7359},[144,9814,5241],{"class":261},[144,9816,9817,9819,9821,9823,9825,9827,9829,9831,9833,9835,9837,9839],{"class":146,"line":7373},[144,9818,5080],{"class":257},[144,9820,2507],{"class":261},[144,9822,1179],{"class":257},[144,9824,1217],{"class":261},[144,9826,4809],{"class":154},[144,9828,398],{"class":261},[144,9830,4830],{"class":154},[144,9832,398],{"class":261},[144,9834,4850],{"class":154},[144,9836,398],{"class":261},[144,9838,4870],{"class":154},[144,9840,546],{"class":261},[144,9842,9843,9845,9847,9849,9851,9853,9855,9857,9859,9861,9863,9865],{"class":146,"line":7378},[144,9844,5281],{"class":261},[144,9846,265],{"class":257},[144,9848,1217],{"class":261},[144,9850,5288],{"class":154},[144,9852,5291],{"class":257},[144,9854,5294],{"class":261},[144,9856,5297],{"class":257},[144,9858,5300],{"class":261},[144,9860,781],{"class":154},[144,9862,398],{"class":261},[144,9864,5307],{"class":154},[144,9866,404],{"class":261},[144,9868,9869,9871,9873,9875,9877,9879,9882,9884,9887,9889,9891,9893,9895,9898,9900,9902,9904,9906,9908],{"class":146,"line":7392},[144,9870,5314],{"class":154},[144,9872,792],{"class":261},[144,9874,438],{"class":257},[144,9876,5321],{"class":158},[144,9878,683],{"class":154},[144,9880,9881],{"class":261},"attempt",[144,9883,5297],{"class":257},[144,9885,9886],{"class":154},"1}",[144,9888,1225],{"class":158},[144,9890,683],{"class":154},[144,9892,5338],{"class":261},[144,9894,689],{"class":154},[144,9896,9897],{"class":158}," after ",[144,9899,683],{"class":154},[144,9901,5356],{"class":261},[144,9903,5359],{"class":257},[144,9905,689],{"class":154},[144,9907,1023],{"class":158},[144,9909,404],{"class":261},[144,9911,9912],{"class":146,"line":7406},[144,9913,5389],{"class":261},[144,9915,9916],{"class":146,"line":7438},[144,9917,5394],{"class":257},[144,9919,9920,9922],{"class":146,"line":7450},[144,9921,5404],{"class":257},[144,9923,9924],{"class":261}," requests.exceptions.RequestException:\n",[144,9926,9927,9929,9931,9933,9935,9937,9939,9941,9943,9945,9947,9949],{"class":146,"line":7460},[144,9928,5413],{"class":261},[144,9930,265],{"class":257},[144,9932,1217],{"class":261},[144,9934,5288],{"class":154},[144,9936,5291],{"class":257},[144,9938,5294],{"class":261},[144,9940,5297],{"class":257},[144,9942,5300],{"class":261},[144,9944,781],{"class":154},[144,9946,398],{"class":261},[144,9948,5307],{"class":154},[144,9950,404],{"class":261},[144,9952,9953,9955,9957,9959,9961,9963,9965,9967,9969,9971,9973,9975,9977,9979,9981,9983,9985,9987,9989],{"class":146,"line":7465},[144,9954,5441],{"class":154},[144,9956,792],{"class":261},[144,9958,438],{"class":257},[144,9960,5321],{"class":158},[144,9962,683],{"class":154},[144,9964,9881],{"class":261},[144,9966,5297],{"class":257},[144,9968,9886],{"class":154},[144,9970,1225],{"class":158},[144,9972,683],{"class":154},[144,9974,5338],{"class":261},[144,9976,689],{"class":154},[144,9978,9897],{"class":158},[144,9980,683],{"class":154},[144,9982,5356],{"class":261},[144,9984,5359],{"class":257},[144,9986,689],{"class":154},[144,9988,1023],{"class":158},[144,9990,404],{"class":261},[144,9992,9993],{"class":146,"line":7472},[144,9994,5492],{"class":261},[144,9996,9997],{"class":146,"line":7494},[144,9998,5498],{"class":257},[144,10000,10001,10003,10005,10007,10009,10011,10013,10015,10017,10019],{"class":146,"line":7525},[144,10002,995],{"class":257},[144,10004,907],{"class":154},[144,10006,792],{"class":261},[144,10008,438],{"class":257},[144,10010,5631],{"class":158},[144,10012,683],{"class":154},[144,10014,5338],{"class":261},[144,10016,689],{"class":154},[144,10018,5640],{"class":158},[144,10020,404],{"class":261},[144,10022,10023],{"class":146,"line":7530},[144,10024,374],{"emptyLinePlaceholder":57},[144,10026,10027],{"class":146,"line":7536},[144,10028,374],{"emptyLinePlaceholder":57},[144,10030,10031,10033,10035],{"class":146,"line":7561},[144,10032,524],{"class":257},[144,10034,5703],{"class":150},[144,10036,5706],{"class":261},[144,10038,10039],{"class":146,"line":7566},[144,10040,10041],{"class":158},"    \"\"\"API コール前に生成 payload をバリデーションします。\"\"\"\n",[144,10043,10044,10046,10048],{"class":146,"line":7571},[144,10045,5729],{"class":261},[144,10047,265],{"class":257},[144,10049,5734],{"class":261},[144,10051,10052,10054,10056,10058,10060],{"class":146,"line":7594},[144,10053,2504],{"class":257},[144,10055,5750],{"class":257},[144,10057,5753],{"class":261},[144,10059,5756],{"class":158},[144,10061,546],{"class":261},[144,10063,10064,10066,10068],{"class":146,"line":7604},[144,10065,5763],{"class":261},[144,10067,5766],{"class":158},[144,10069,404],{"class":261},[144,10071,10072,10074,10076,10078,10080,10082,10084,10086,10088,10090],{"class":146,"line":7610},[144,10073,2504],{"class":257},[144,10075,5750],{"class":257},[144,10077,5753],{"class":261},[144,10079,5779],{"class":158},[144,10081,1162],{"class":261},[144,10083,5784],{"class":257},[144,10085,5750],{"class":257},[144,10087,5789],{"class":261},[144,10089,5779],{"class":158},[144,10091,5794],{"class":261},[144,10093,10094,10096,10099],{"class":146,"line":7628},[144,10095,5763],{"class":261},[144,10097,10098],{"class":158},"\"'prompt' is required\"",[144,10100,404],{"class":261},[144,10102,10103,10105,10107,10109,10111,10113,10115],{"class":146,"line":7633},[144,10104,5817],{"class":261},[144,10106,265],{"class":257},[144,10108,5753],{"class":261},[144,10110,5824],{"class":158},[144,10112,398],{"class":261},[144,10114,1352],{"class":154},[144,10116,404],{"class":261},[144,10118,10119,10121,10123,10125,10127,10129,10131,10133,10135],{"class":146,"line":7638},[144,10120,2504],{"class":257},[144,10122,5837],{"class":261},[144,10124,646],{"class":257},[144,10126,5842],{"class":154},[144,10128,5845],{"class":257},[144,10130,5837],{"class":261},[144,10132,5850],{"class":257},[144,10134,5853],{"class":154},[144,10136,858],{"class":261},[144,10138,10139,10141,10143,10145,10147,10149,10151,10153],{"class":146,"line":7651},[144,10140,5763],{"class":261},[144,10142,438],{"class":257},[144,10144,5864],{"class":158},[144,10146,683],{"class":154},[144,10148,1775],{"class":261},[144,10150,689],{"class":154},[144,10152,447],{"class":158},[144,10154,404],{"class":261},[144,10156,10157,10159,10161,10163,10165,10167,10169],{"class":146,"line":7665},[144,10158,5910],{"class":261},[144,10160,265],{"class":257},[144,10162,5753],{"class":261},[144,10164,5917],{"class":158},[144,10166,398],{"class":261},[144,10168,1368],{"class":158},[144,10170,404],{"class":261},[144,10172,10173,10175,10177,10179,10181,10183,10185,10187,10189,10191,10193],{"class":146,"line":7692},[144,10174,2504],{"class":257},[144,10176,5930],{"class":261},[144,10178,5933],{"class":257},[144,10180,5936],{"class":257},[144,10182,5893],{"class":261},[144,10184,4011],{"class":158},[144,10186,398],{"class":261},[144,10188,1368],{"class":158},[144,10190,398],{"class":261},[144,10192,3708],{"class":158},[144,10194,10195],{"class":261},"}:\n",[144,10197,10198,10200,10202,10205,10207,10209,10211,10213],{"class":146,"line":7706},[144,10199,5763],{"class":261},[144,10201,438],{"class":257},[144,10203,10204],{"class":158},"\"Invalid quality: ",[144,10206,683],{"class":154},[144,10208,1783],{"class":261},[144,10210,689],{"class":154},[144,10212,447],{"class":158},[144,10214,404],{"class":261},[144,10216,10218,10220],{"class":146,"line":10217},99,[144,10219,2504],{"class":257},[144,10221,6205],{"class":261},[144,10223,10225,10227,10229,10231,10234,10236,10238,10240,10242,10244,10246,10248,10250,10252,10254,10256,10258,10260,10262,10264,10266],{"class":146,"line":10224},100,[144,10226,6210],{"class":257},[144,10228,5208],{"class":154},[144,10230,792],{"class":261},[144,10232,10233],{"class":158},"\"Validation failed:",[144,10235,1670],{"class":154},[144,10237,447],{"class":158},[144,10239,6226],{"class":257},[144,10241,6229],{"class":158},[144,10243,1670],{"class":154},[144,10245,447],{"class":158},[144,10247,6236],{"class":261},[144,10249,438],{"class":257},[144,10251,6241],{"class":158},[144,10253,683],{"class":154},[144,10255,5560],{"class":261},[144,10257,689],{"class":154},[144,10259,447],{"class":158},[144,10261,6252],{"class":257},[144,10263,6255],{"class":261},[144,10265,1179],{"class":257},[144,10267,6260],{"class":261},[144,10269,10271],{"class":146,"line":10270},101,[144,10272,374],{"emptyLinePlaceholder":57},[144,10274,10276],{"class":146,"line":10275},102,[144,10277,374],{"emptyLinePlaceholder":57},[144,10279,10281,10283,10285],{"class":146,"line":10280},103,[144,10282,524],{"class":257},[144,10284,2450],{"class":150},[144,10286,2453],{"class":261},[144,10288,10290],{"class":146,"line":10289},104,[144,10291,10292],{"class":158},"    \"\"\"pending または processing 状態のタスクをキャンセルします。\"\"\"\n",[144,10294,10296,10298,10300],{"class":146,"line":10295},105,[144,10297,1427],{"class":261},[144,10299,265],{"class":257},[144,10301,1432],{"class":261},[144,10303,10305,10307,10309,10311,10313,10315,10317,10319,10321],{"class":146,"line":10304},106,[144,10306,1437],{"class":257},[144,10308,447],{"class":158},[144,10310,677],{"class":154},[144,10312,680],{"class":158},[144,10314,683],{"class":154},[144,10316,686],{"class":261},[144,10318,689],{"class":154},[144,10320,2485],{"class":158},[144,10322,450],{"class":261},[144,10324,10326,10328,10330],{"class":146,"line":10325},107,[144,10327,1455],{"class":699},[144,10329,265],{"class":257},[144,10331,705],{"class":154},[144,10333,10335],{"class":146,"line":10334},108,[144,10336,1483],{"class":261},[144,10338,10340,10342,10344,10346,10348],{"class":146,"line":10339},109,[144,10341,2504],{"class":257},[144,10343,2507],{"class":261},[144,10345,852],{"class":257},[144,10347,2512],{"class":154},[144,10349,858],{"class":261},[144,10351,10353,10355,10357,10359,10361,10363,10365,10367,10370],{"class":146,"line":10352},110,[144,10354,789],{"class":154},[144,10356,792],{"class":261},[144,10358,438],{"class":257},[144,10360,919],{"class":158},[144,10362,683],{"class":154},[144,10364,686],{"class":261},[144,10366,689],{"class":154},[144,10368,10369],{"class":158}," cancelled.\"",[144,10371,404],{"class":261},[144,10373,10375,10377],{"class":146,"line":10374},111,[144,10376,2540],{"class":257},[144,10378,858],{"class":261},[144,10380,10382,10384,10386,10388,10390,10392,10394,10396,10398],{"class":146,"line":10381},112,[144,10383,789],{"class":154},[144,10385,792],{"class":261},[144,10387,438],{"class":257},[144,10389,2553],{"class":158},[144,10391,683],{"class":154},[144,10393,2558],{"class":261},[144,10395,689],{"class":154},[144,10397,447],{"class":158},[144,10399,404],{"class":261},[144,10401,10403],{"class":146,"line":10402},113,[144,10404,374],{"emptyLinePlaceholder":57},[144,10406,10408],{"class":146,"line":10407},114,[144,10409,374],{"emptyLinePlaceholder":57},[144,10411,10413],{"class":146,"line":10412},115,[144,10414,10415],{"class":173},"# ── 例 1：テキストから動画 ────────────────────────────────────\n",[144,10417,10419,10421,10423],{"class":146,"line":10418},116,[144,10420,524],{"class":257},[144,10422,1286],{"class":150},[144,10424,1289],{"class":261},[144,10426,10428,10430,10432],{"class":146,"line":10427},117,[144,10429,1294],{"class":261},[144,10431,265],{"class":257},[144,10433,426],{"class":261},[144,10435,10437,10439,10441,10443],{"class":146,"line":10436},118,[144,10438,1303],{"class":158},[144,10440,435],{"class":261},[144,10442,1308],{"class":158},[144,10444,450],{"class":261},[144,10446,10448,10450],{"class":146,"line":10447},119,[144,10449,1319],{"class":158},[144,10451,1322],{"class":261},[144,10453,10455],{"class":146,"line":10454},120,[144,10456,1327],{"class":158},[144,10458,10460],{"class":146,"line":10459},121,[144,10461,1332],{"class":158},[144,10463,10465],{"class":146,"line":10464},122,[144,10466,1337],{"class":158},[144,10468,10470],{"class":146,"line":10469},123,[144,10471,1342],{"class":261},[144,10473,10475,10477,10479,10481],{"class":146,"line":10474},124,[144,10476,1347],{"class":158},[144,10478,435],{"class":261},[144,10480,1352],{"class":154},[144,10482,450],{"class":261},[144,10484,10486,10488,10490,10492],{"class":146,"line":10485},125,[144,10487,1363],{"class":158},[144,10489,435],{"class":261},[144,10491,1368],{"class":158},[144,10493,450],{"class":261},[144,10495,10497,10499,10501,10503],{"class":146,"line":10496},126,[144,10498,1379],{"class":158},[144,10500,435],{"class":261},[144,10502,1384],{"class":158},[144,10504,450],{"class":261},[144,10506,10508,10510,10512],{"class":146,"line":10507},127,[144,10509,1395],{"class":158},[144,10511,435],{"class":261},[144,10513,3736],{"class":154},[144,10515,10517],{"class":146,"line":10516},128,[144,10518,1407],{"class":261},[144,10520,10522],{"class":146,"line":10521},129,[144,10523,10524],{"class":261},"    validate_payload(payload)\n",[144,10526,10528,10530,10532],{"class":146,"line":10527},130,[144,10529,1496],{"class":261},[144,10531,265],{"class":257},[144,10533,8390],{"class":261},[144,10535,10537,10539,10541,10543,10546,10548,10550,10552,10554,10556,10559,10561,10563,10565,10567,10569,10571,10573,10576],{"class":146,"line":10536},131,[144,10538,1101],{"class":154},[144,10540,792],{"class":261},[144,10542,438],{"class":257},[144,10544,10545],{"class":158},"\"Task: ",[144,10547,683],{"class":154},[144,10549,1529],{"class":261},[144,10551,1532],{"class":158},[144,10553,1535],{"class":261},[144,10555,689],{"class":154},[144,10557,10558],{"class":158}," (ETA: ",[144,10560,683],{"class":154},[144,10562,1529],{"class":261},[144,10564,1559],{"class":158},[144,10566,1562],{"class":261},[144,10568,1565],{"class":158},[144,10570,1535],{"class":261},[144,10572,689],{"class":154},[144,10574,10575],{"class":158},"s)\"",[144,10577,404],{"class":261},[144,10579,10581,10583,10585,10587,10589],{"class":146,"line":10580},132,[144,10582,1618],{"class":261},[144,10584,265],{"class":257},[144,10586,1623],{"class":261},[144,10588,1626],{"class":158},[144,10590,1629],{"class":261},[144,10592,10594,10597,10599,10601,10603,10606,10609],{"class":146,"line":10593},133,[144,10595,10596],{"class":261},"    download_video(result[",[144,10598,1651],{"class":158},[144,10600,1562],{"class":261},[144,10602,781],{"class":154},[144,10604,10605],{"class":261},"], ",[144,10607,10608],{"class":158},"\"text_to_video.mp4\"",[144,10610,404],{"class":261},[144,10612,10614],{"class":146,"line":10613},134,[144,10615,374],{"emptyLinePlaceholder":57},[144,10617,10619],{"class":146,"line":10618},135,[144,10620,374],{"emptyLinePlaceholder":57},[144,10622,10624],{"class":146,"line":10623},136,[144,10625,10626],{"class":173},"# ── 例 2：画像から動画 ────────────────────────────────────────\n",[144,10628,10630,10632,10634],{"class":146,"line":10629},137,[144,10631,524],{"class":257},[144,10633,2637],{"class":150},[144,10635,1289],{"class":261},[144,10637,10639,10641,10643],{"class":146,"line":10638},138,[144,10640,1294],{"class":261},[144,10642,265],{"class":257},[144,10644,426],{"class":261},[144,10646,10648,10650,10652,10654],{"class":146,"line":10647},139,[144,10649,1303],{"class":158},[144,10651,435],{"class":261},[144,10653,1308],{"class":158},[144,10655,450],{"class":261},[144,10657,10659,10661],{"class":146,"line":10658},140,[144,10660,1319],{"class":158},[144,10662,1322],{"class":261},[144,10664,10666],{"class":146,"line":10665},141,[144,10667,2668],{"class":158},[144,10669,10671],{"class":146,"line":10670},142,[144,10672,2673],{"class":158},[144,10674,10676],{"class":146,"line":10675},143,[144,10677,10678],{"class":158},"            \"across the frame.\"\n",[144,10680,10682],{"class":146,"line":10681},144,[144,10683,1342],{"class":261},[144,10685,10687,10689,10692,10695],{"class":146,"line":10686},145,[144,10688,2687],{"class":158},[144,10690,10691],{"class":261},": [",[144,10693,10694],{"class":158},"\"https://example.com/your-image.jpg\"",[144,10696,10697],{"class":261},"],\n",[144,10699,10701,10703,10705,10707],{"class":146,"line":10700},146,[144,10702,1347],{"class":158},[144,10704,435],{"class":261},[144,10706,1352],{"class":154},[144,10708,450],{"class":261},[144,10710,10712,10714,10716],{"class":146,"line":10711},147,[144,10713,1363],{"class":158},[144,10715,435],{"class":261},[144,10717,8369],{"class":158},[144,10719,10721],{"class":146,"line":10720},148,[144,10722,1407],{"class":261},[144,10724,10726],{"class":146,"line":10725},149,[144,10727,10524],{"class":261},[144,10729,10731,10733,10735],{"class":146,"line":10730},150,[144,10732,1496],{"class":261},[144,10734,265],{"class":257},[144,10736,8390],{"class":261},[144,10738,10740,10742,10744,10746,10748,10750,10752,10754,10756,10758,10760],{"class":146,"line":10739},151,[144,10741,1101],{"class":154},[144,10743,792],{"class":261},[144,10745,438],{"class":257},[144,10747,10545],{"class":158},[144,10749,683],{"class":154},[144,10751,1529],{"class":261},[144,10753,1532],{"class":158},[144,10755,1535],{"class":261},[144,10757,689],{"class":154},[144,10759,447],{"class":158},[144,10761,404],{"class":261},[144,10763,10765,10767,10769,10771,10773],{"class":146,"line":10764},152,[144,10766,1618],{"class":261},[144,10768,265],{"class":257},[144,10770,1623],{"class":261},[144,10772,1626],{"class":158},[144,10774,1629],{"class":261},[144,10776,10778,10780,10782,10784,10786,10788,10791],{"class":146,"line":10777},153,[144,10779,10596],{"class":261},[144,10781,1651],{"class":158},[144,10783,1562],{"class":261},[144,10785,781],{"class":154},[144,10787,10605],{"class":261},[144,10789,10790],{"class":158},"\"image_to_video.mp4\"",[144,10792,404],{"class":261},[144,10794,10796],{"class":146,"line":10795},154,[144,10797,374],{"emptyLinePlaceholder":57},[144,10799,10801],{"class":146,"line":10800},155,[144,10802,374],{"emptyLinePlaceholder":57},[144,10804,10806],{"class":146,"line":10805},156,[144,10807,10808],{"class":173},"# ── 例 3：縦型ソーシャルメディア動画 ──────────────────────────\n",[144,10810,10812,10814,10817],{"class":146,"line":10811},157,[144,10813,524],{"class":257},[144,10815,10816],{"class":150}," social_media_video",[144,10818,1289],{"class":261},[144,10820,10822,10824,10826],{"class":146,"line":10821},158,[144,10823,1294],{"class":261},[144,10825,265],{"class":257},[144,10827,426],{"class":261},[144,10829,10831,10833,10835,10837],{"class":146,"line":10830},159,[144,10832,1303],{"class":158},[144,10834,435],{"class":261},[144,10836,1308],{"class":158},[144,10838,450],{"class":261},[144,10840,10842,10844],{"class":146,"line":10841},160,[144,10843,1319],{"class":158},[144,10845,1322],{"class":261},[144,10847,10849],{"class":146,"line":10848},161,[144,10850,10851],{"class":158},"            \"A barista pours latte art in slow motion. \"\n",[144,10853,10855],{"class":146,"line":10854},162,[144,10856,10857],{"class":158},"            \"Close-up overhead shot, warm cafe lighting.\"\n",[144,10859,10861],{"class":146,"line":10860},163,[144,10862,1342],{"class":261},[144,10864,10866,10868,10870,10872],{"class":146,"line":10865},164,[144,10867,1347],{"class":158},[144,10869,435],{"class":261},[144,10871,3696],{"class":154},[144,10873,450],{"class":261},[144,10875,10877,10879,10881,10883],{"class":146,"line":10876},165,[144,10878,1363],{"class":158},[144,10880,435],{"class":261},[144,10882,3708],{"class":158},[144,10884,450],{"class":261},[144,10886,10888,10890,10892,10894],{"class":146,"line":10887},166,[144,10889,1379],{"class":158},[144,10891,435],{"class":261},[144,10893,3720],{"class":158},[144,10895,450],{"class":261},[144,10897,10899,10901,10903],{"class":146,"line":10898},167,[144,10900,1395],{"class":158},[144,10902,435],{"class":261},[144,10904,3736],{"class":154},[144,10906,10908],{"class":146,"line":10907},168,[144,10909,1407],{"class":261},[144,10911,10913],{"class":146,"line":10912},169,[144,10914,10524],{"class":261},[144,10916,10918,10920,10922],{"class":146,"line":10917},170,[144,10919,1496],{"class":261},[144,10921,265],{"class":257},[144,10923,8390],{"class":261},[144,10925,10927,10929,10931,10933,10935,10937,10939,10941,10943,10945,10947],{"class":146,"line":10926},171,[144,10928,1101],{"class":154},[144,10930,792],{"class":261},[144,10932,438],{"class":257},[144,10934,10545],{"class":158},[144,10936,683],{"class":154},[144,10938,1529],{"class":261},[144,10940,1532],{"class":158},[144,10942,1535],{"class":261},[144,10944,689],{"class":154},[144,10946,447],{"class":158},[144,10948,404],{"class":261},[144,10950,10952,10954,10956,10958,10960],{"class":146,"line":10951},172,[144,10953,1618],{"class":261},[144,10955,265],{"class":257},[144,10957,1623],{"class":261},[144,10959,1626],{"class":158},[144,10961,1629],{"class":261},[144,10963,10965,10967,10969,10971,10973,10975,10978],{"class":146,"line":10964},173,[144,10966,10596],{"class":261},[144,10968,1651],{"class":158},[144,10970,1562],{"class":261},[144,10972,781],{"class":154},[144,10974,10605],{"class":261},[144,10976,10977],{"class":158},"\"social_video.mp4\"",[144,10979,404],{"class":261},[144,10981,10983],{"class":146,"line":10982},174,[144,10984,374],{"emptyLinePlaceholder":57},[144,10986,10988],{"class":146,"line":10987},175,[144,10989,374],{"emptyLinePlaceholder":57},[144,10991,10993,10995,10997,10999,11001],{"class":146,"line":10992},176,[144,10994,1719],{"class":257},[144,10996,1722],{"class":154},[144,10998,1725],{"class":257},[144,11000,1728],{"class":158},[144,11002,858],{"class":261},[144,11004,11006,11008,11010,11013],{"class":146,"line":11005},177,[144,11007,1101],{"class":154},[144,11009,792],{"class":261},[144,11011,11012],{"class":158},"\"=== テキストから動画 ===\"",[144,11014,404],{"class":261},[144,11016,11018],{"class":146,"line":11017},178,[144,11019,1735],{"class":261},[144,11021,11023],{"class":146,"line":11022},179,[144,11024,11025],{"class":173},"    # print(\"\\n=== 画像から動画 ===\")\n",[144,11027,11029],{"class":146,"line":11028},180,[144,11030,11031],{"class":173},"    # image_to_video()  # コメントを外して画像 URL を設定\n",[144,11033,11035],{"class":146,"line":11034},181,[144,11036,11037],{"class":173},"    # print(\"\\n=== ソーシャルメディア動画 ===\")\n",[144,11039,11041],{"class":146,"line":11040},182,[144,11042,11043],{"class":173},"    # social_media_video()\n",[17,11045,11046],{},[10,11047,11048,11050,11051,11053,11054,11057],{},[22,11049,132],{}," 現在利用可能なモデルでテストするには、",[27,11052,1308],{}," を ",[27,11055,11056],{},"\"seedance-1.5-pro\""," に変更してください。API インターフェースは同一です — 同じエンドポイント、同じパラメータ、同じレスポンス形式。Seedance 2.0 が完全にリリースされたら、モデル名を戻すだけです。",[10,11059,11060],{},[22,11061,11062],{},[36,11063,11065],{"href":38,"rel":11064},[40],"構築を始めよう → EvoLink で無料 API Key を取得",[11067,11068,11069],"style",{},"html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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 pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":140,"searchDepth":165,"depth":165,"links":11071},[11072,11075,11076,11077,11081,11086,11091,11095,11101,11109,11110,11115,11127],{"id":49,"depth":165,"text":50,"children":11073},[11074],{"id":93,"depth":177,"text":93},{"id":203,"depth":165,"text":204},{"id":309,"depth":165,"text":310},{"id":1265,"depth":165,"text":1266,"children":11078},[11079,11080],{"id":1845,"depth":177,"text":1846},{"id":2173,"depth":177,"text":2174},{"id":2217,"depth":165,"text":2218,"children":11082},[11083,11084,11085],{"id":2267,"depth":177,"text":2267},{"id":2346,"depth":177,"text":2347},{"id":2435,"depth":177,"text":2435},{"id":2601,"depth":165,"text":2602,"children":11087},[11088,11089,11090],{"id":2940,"depth":177,"text":2941},{"id":3216,"depth":177,"text":3216},{"id":3291,"depth":177,"text":3292},{"id":3386,"depth":165,"text":3386,"children":11092},[11093,11094],{"id":3640,"depth":177,"text":3640},{"id":4048,"depth":177,"text":4048},{"id":4159,"depth":165,"text":4159,"children":11096},[11097,11098,11099,11100],{"id":4165,"depth":177,"text":4165},{"id":4674,"depth":177,"text":4674},{"id":4888,"depth":177,"text":4888},{"id":5687,"depth":177,"text":5688},{"id":6287,"depth":165,"text":6288,"children":11102},[11103,11104,11105,11106,11107,11108],{"id":6298,"depth":177,"text":6298},{"id":6476,"depth":177,"text":6477},{"id":6542,"depth":177,"text":6543},{"id":7797,"depth":177,"text":7798},{"id":7935,"depth":177,"text":7936},{"id":8114,"depth":177,"text":8115},{"id":8206,"depth":165,"text":8207},{"id":8793,"depth":165,"text":8793,"children":11111},[11112,11113,11114],{"id":8799,"depth":177,"text":8799},{"id":8841,"depth":177,"text":8841},{"id":8866,"depth":177,"text":8866},{"id":8918,"depth":165,"text":8918,"children":11116},[11117,11118,11119,11120,11121,11122,11123,11124,11125,11126],{"id":8921,"depth":177,"text":8922},{"id":8931,"depth":177,"text":8932},{"id":8941,"depth":177,"text":8942},{"id":8951,"depth":177,"text":8952},{"id":8966,"depth":177,"text":8967},{"id":8983,"depth":177,"text":8984},{"id":8997,"depth":177,"text":8998},{"id":9016,"depth":177,"text":9017},{"id":9027,"depth":177,"text":9028},{"id":9047,"depth":177,"text":9048},{"id":9060,"depth":165,"text":9060},"Python で Seedance 2.0 API を使って AI 動画を生成するステップバイステップチュートリアル。テキストから動画、画像から動画、非同期 polling、webhook、エラー処理を網羅。","md",{"date":11131,"image":11132,"seoTitle":11133,"author":11134},"2026-02-27","/s2-hero-api-tutorial.webp","Seedance 2.0 API チュートリアル：Python で初めての AI 動画生成（2026）","J @ EvoLink","/ja/blog/seedance-2-api-tutorial-python",{"title":5,"description":11128},"ja/blog/seedance-2-api-tutorial-python","HRth4VTeCZCpDjNa2cFf68BCbP8r4B0gr4--ncMhzrQ",1775067565011]