{"id":"media-proxy","name":"media-proxy","summary":"共有ヘルパーで、すべての有料メディア生成(FALの画像/動画、ElevenLabsの音楽)をGooseWorksプロキシ経由でルーティングし、すべての通話が広告代理に請求されるようにします。","body":"# media-proxy\n\nThe foundation capability for paid media in the video-ad pipeline. It fixes the\nauth-path conflict where engine scripts called FAL/ElevenLabs **directly** (billing\nthe wrong account): all paid calls now go through\n`<api_base>/api/internal/{fal-proxy,elevenlabs-proxy}` with `?token=&agent_id=`, which\n**bills the Ads agent**.\n\n## Crash-resume (never lose / double-bill a paid render)\n\nA FAL submit BILLS immediately, but the local backend can blip during a multi-minute\nrender. Two built-in protections (automatic for every capability that imports this):\n- **Poll-through-outage** — `_fal_run`'s poll loop re-attaches to the same status/result\n  URL through `connection refused` / timeout blips instead of crashing.\n- **Persist + resume** — each submit's `request_id` + poll URLs are written to\n  `~/.gooseworks/pending-fal-jobs/`. If the poller still dies, **re-attach instead of\n  re-firing** (re-firing double-bills): `resume_fal(request_id)` in Python, or the CLI:\n\n  ```bash\n  resume.py --list                              # resumable (submitted, unfinished) jobs\n  resume.py --request-id <id> --out final.mp4   # poll to completion + download\n  ```\n  `resume_fal` NEVER re-submits, so it can't double-charge.\n\n## Use it\n\n```python\nfrom media_proxy import fal_generate, fal_generate_video, eleven_music, download\n\n# image (nano-banana / gpt-image / etc.) — inputs must be PUBLIC urls\nimg = fal_generate(\"fal-ai/nano-banana/edit\",\n                   {\"prompt\": p, \"image_urls\": [product_url], \"aspect_ratio\": \"9:16\"})\n# video i2v (kling / seedance / veo)\nvid = fal_generate_video(\"fal-ai/kling-video/v2.1/standard/image-to-video\",\n                         {\"prompt\": p, \"image_url\": keyframe_url, \"duration\": \"10\"})\n# music bed\neleven_music(prompt, 10500, \"music.mp3\", force_instrumental=True)\n```\n\n## Contracts (load-bearing)\n\n- **Bills the Ads agent** — `?token=&agent_id=` from `~/.gooseworks/credentials.json`\n  (the CLI writes it; run `gooseworks login` if missing).\n- **Host-swap the FAL queue URLs** — submit returns `status_url`/`response_url` on\n  `queue.fal.run`; the helper rewrites them to the proxy base (keeps the path). Never\n  poll `queue.fal.run` directly (401 + burns credits).\n- **FAL inputs that are local files must be PUBLIC urls.** The orchestrator hosts a\n  local image/audio via the MCP `get_upload_url` → `get_download_url` presigned URL and\n  passes THAT url in. This module does not do MCP uploads (prefer the presigned url;\n  `fal-storage-proxy` may 404).\n- **Only the final `*.fal.media` url is a real public URL** — everything else is behind\n  the proxy.\n\n## Related\n- Used by `create-image-fal`, `create-video-fal`, `create-music-elevenlabs`.\n- The `goose-video` orchestrator hosts local inputs (MCP upload → presign) before calling these.","author":"@gooseworks-ai","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/gooseworks-ai/goose-skills/tree/main/skills/ads/capabilities/media-proxy","license":"MIT","category":"coding","lang":"en","tokens":743,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"scripts/media_proxy.py","size":15221,"sha256":"a93ee72308f14c6c1ce8ee2101bdf2551cae44597fc90626072d5201b1de840d"},{"path":"scripts/resume.py","size":2268,"sha256":"398f32a610a517598690e400e640a20c35896464316c91d022f83e73269c1a06"},{"path":"skill.meta.json","size":259,"sha256":"0294603c9a94235da95e62a12372fe98756ecce6e570e29d7b58d511ecf019f4"},{"path":"tests/smoke-test.md","size":183,"sha256":"b03b1705fca5498db9291c4eb3ae4bd417f953962fc54c7d0f1c311f19ab4cd0"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[{"code":"code.credentials","kind":"dangerous-code","where":"scripts/media_proxy.py:10","excerpt":"credentials.json","message":"reads credential files","severity":"warn"}],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":[]}}