{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Local Video Upload Service","siteUrl":"https://docs.bria.ai","llmstxt":{"hide":false,"title":"Bria AI API","description":"bria.ai helps you build products and workflows by delivering controllable, easy-to-integrate and safe generative visual AI capabilities.","details":{"path":"_llmstxt-details.md"},"sections":[{"title":"Integrations","description":"MCP server, Claude Skill, and Python SDK.","includeFiles":["MCP-authentication.md","integration-methods/bria-skill.md","integration-methods/python-sdk.md"],"excludeFiles":[]},{"title":"Getting Started","description":"Authentication, API overview, and platform concepts.","includeFiles":["index.md","products-overview.md","safety.md","vgl.md","best-practices-overview.md"],"excludeFiles":[]},{"title":"Image Generation","description":"Generate images using text prompts or structured JSON via FIBO models.","includeFiles":["image-generation.md","image-generation.yaml"],"excludeFiles":[]},{"title":"Image Editing","description":"Edit, transform, and enhance images with 20+ specialized endpoints.","includeFiles":["image-editing.md","image-editing.yaml"],"excludeFiles":[]},{"title":"Video Editing","description":"Remove backgrounds (REST async or real-time streaming), erase objects, upscale, and generate masks for video.","includeFiles":["video-editing.md","local-video-upload-service.md","video-editing.yaml","streaming-rmbg.md"],"excludeFiles":[]},{"title":"Product Shot Editing","description":"SKU packshots, lifestyle scenes, and automotive product imagery.","includeFiles":["product-shot-editing.md","product-shot-editing.yaml"],"excludeFiles":[]},{"title":"Optional","description":"Tailored generation, ads, image onboarding, and attribution.","includeFiles":["tailored-generation.md","campaign-generation.md","image-onboarding.md","bria-attribution-service.md","ad-generation.md","tailored-generation.yaml","campaign-generation.yaml","image-onboarding.yaml","bria-attribution-service.yaml","ad-generation.yaml"],"excludeFiles":[]}],"excludeFiles":["_llmstxt-details.md","_partials.md","CHANGELOG.md"]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"local-video-upload-service","__idx":0},"children":["Local Video Upload Service"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Upload a local video file and use it as input to any Bria video editing endpoint."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Most Bria video endpoints accept a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["video"]}," parameter that points to a publicly accessible URL. When your video lives on your own machine rather than at a public URL, use the upload service to get a temporary, hosted URL you can pass straight into those endpoints."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The flow is three steps:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Request a presigned upload URL"]}," — call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /v2/video/upload"]}," to get an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]},", the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_fields"]}," needed to authenticate the upload, and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}," your video will live at."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Upload the file"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," the video directly to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]}," as multipart form data."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Process the video"]}," — pass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}," as the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["video"]}," input to any video editing endpoint."]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Using the Python SDK?"]}," The Bria Python client wraps this whole flow — see the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#"},"children":["SDK docs"]}," for the one-call helper. The instructions below describe the underlying HTTP API for everyone else."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1--request-a-presigned-upload-url","__idx":1},"children":["Step 1 — Request a presigned upload URL"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /v2/video/upload\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Body"]}," (JSON)"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Required"},"children":["Required"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["media_type"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["MIME type of the video you intend to upload, e.g. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"video/mp4\""]},". When omitted, the server falls back to a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"video/\""]}," content-type prefix."]}]}]}]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{ \"media_type\": \"video/mp4\" }\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["An empty body (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{}"]},") is also valid."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Response"]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["result"]},")"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Presigned URL to upload your video to. Valid for ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["1 hour"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_fields"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["dict"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Presigned form fields (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["key"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["policy"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["signature"]},", etc.) that must be included in the upload ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," to authenticate it."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The URL your video will be available at after upload. Pass this as the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["video"]}," input to any video endpoint. Valid for ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["1 day"]},"."]}]}]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2--upload-the-file","__idx":2},"children":["Step 2 — Upload the file"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," the video to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]}," as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["multipart/form-data"]},". The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_fields"]}," must be sent as form fields ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["before"]}," the file field — they are validated in order, so the actual file must come last."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"with open(video_path, \"rb\") as f:\n    # All presigned fields first, then the file last\n    files = {k: (None, v) for k, v in upload_fields.items()}\n    files[\"file\"] = (video_path, f, \"video/mp4\")\n\n    resp = requests.post(upload_url, files=files)\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A successful upload returns ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HTTP 204 No Content"]},"."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3--process-the-video","__idx":3},"children":["Step 3 — Process the video"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Pass ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}," as the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["video"]}," input to any video editing endpoint."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"POST /v2/video/edit/remove_background\n"},"children":[]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{ \"video\": \"<file_url>\" }\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Video editing endpoints are ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["asynchronous"]},": a successful call returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HTTP 202"]}," with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["request_id"]}," and a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status_url"]},". Poll ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status_url"]}," until ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["COMPLETED"]}," (or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FAILED"]},"); the finished video is then available at ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["result.video_url"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"request_id\": \"04e104bab7e44319bbf2427d64d8c313\",\n  \"status_url\": \"https://engine.prod.bria-api.com/v2/status/04e104bab7e44319bbf2427d64d8c313\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"limits--expiry","__idx":4},"children":["Limits & expiry"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Constraint"},"children":["Constraint"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Value"},"children":["Value"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Content type"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Video files only"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Max file size"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["1 GB"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]}," validity"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["1 hour"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}," validity"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["1 day"]}]}]}]}]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Security note:"]}," Both ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["upload_url"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["file_url"]}," are unauthenticated — anyone holding either can upload to or download from your file. Treat them as secrets and don't share them beyond your processing pipeline."]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"full-example","__idx":5},"children":["Full example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This script runs the complete flow: request a presigned URL, upload a local video, submit it to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["remove_background"]},", and poll until the output video is ready."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import time\nimport requests\n\nBASE_URL = \"https://engine.prod.bria-api.com\"\nAPI_TOKEN = \"<YOUR_API_TOKEN>\"\nHEADERS = {\"api_token\": API_TOKEN}\n\n\ndef get_presigned_url(media_type: str = \"video/mp4\") -> dict:\n    \"\"\"Step 1 — request a presigned POST URL to upload the video.\"\"\"\n    resp = requests.post(\n        f\"{BASE_URL}/v2/video/upload\",\n        json={\"media_type\": media_type},\n        headers=HEADERS,\n    )\n    resp.raise_for_status()\n    return resp.json()[\"result\"]\n\n\ndef upload_video(upload_url: str, upload_fields: dict, video_path: str) -> None:\n    \"\"\"Step 2 — upload the video directly using the presigned POST URL.\n\n    The upload_fields (key, policy, signature, etc.) must be sent as\n    multipart form fields *before* the file field — they are validated\n    in order, so the file must come last.\n    \"\"\"\n    with open(video_path, \"rb\") as f:\n        files = {k: (None, v) for k, v in upload_fields.items()}\n        files[\"file\"] = (video_path, f, \"video/mp4\")\n        resp = requests.post(upload_url, files=files)\n\n    # A presigned POST returns 204 No Content on success\n    if resp.status_code != 204:\n        raise RuntimeError(f\"Upload failed: HTTP {resp.status_code}\\n{resp.text}\")\n\n\ndef submit_remove_background(file_url: str) -> str:\n    \"\"\"Step 3a — submit the uploaded video to a video editing endpoint.\n\n    Video editing endpoints are async — this returns a status_url to poll.\n    \"\"\"\n    resp = requests.post(\n        f\"{BASE_URL}/v2/video/edit/remove_background\",\n        json={\"video\": file_url},\n        headers=HEADERS,\n    )\n    resp.raise_for_status()\n    return resp.json()[\"status_url\"]\n\n\ndef wait_for_result(status_url: str, interval: float = 5.0, timeout: float = 600.0) -> dict:\n    \"\"\"Step 3b — poll status_url until the job is COMPLETED or FAILED.\"\"\"\n    deadline = time.monotonic() + timeout\n    while time.monotonic() < deadline:\n        resp = requests.get(status_url, headers=HEADERS)\n        resp.raise_for_status()\n        data = resp.json()\n        if data[\"status\"] == \"COMPLETED\":\n            return data[\"result\"]\n        if data[\"status\"] in (\"FAILED\", \"ERROR\"):\n            raise RuntimeError(f\"Job failed: {data}\")\n        time.sleep(interval)\n    raise TimeoutError(f\"Job did not complete within {timeout}s\")\n\n\ndef main():\n    video_path = \"path/to/video.mp4\"\n\n    upload     = get_presigned_url()\n    upload_video(upload[\"upload_url\"], upload[\"upload_fields\"], video_path)\n    status_url = submit_remove_background(upload[\"file_url\"])\n    result     = wait_for_result(status_url)\n\n    print(result[\"video_url\"])\n\n\nif __name__ == \"__main__\":\n    main()\n","lang":"python"},"children":[]}]},"headings":[{"value":"Local Video Upload Service","id":"local-video-upload-service","depth":1},{"value":"Step 1 — Request a presigned upload URL","id":"step-1--request-a-presigned-upload-url","depth":2},{"value":"Step 2 — Upload the file","id":"step-2--upload-the-file","depth":2},{"value":"Step 3 — Process the video","id":"step-3--process-the-video","depth":2},{"value":"Limits & expiry","id":"limits--expiry","depth":2},{"value":"Full example","id":"full-example","depth":2}],"frontmatter":{"seo":{"title":"Local Video Upload Service"}},"lastModified":"2026-05-31T16:31:09.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/local-video-upload-service","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}