Alchemy RecipeAdvancedworkflow

Video marketing campaign from script to multilingual distribution

Published

You've spent weeks perfecting a video script. Your marketing message is sharp, your call-to-action is clear, and you know it will resonate with your audience. Then reality hits: you need to produce this video in five different languages, distribute it across multiple platforms, and coordinate dozens of manual steps to make it happen. By the time you're done, your script feels stale and market conditions have shifted. For more on this, see From Script to Polished Video: Using AI for Demo and Mark....

This workflow eliminates that friction entirely. We're combining Hour One (AI video generation) with Vidau AI (multilingual dubbing and subtitling) to automate the journey from script to fully localised video content ready for distribution. The entire pipeline runs without any manual handoffs between tools; once you trigger it, the system generates your video, dubs it into your target languages, creates matching subtitles, and prepares assets for publication.... For more on this, see SEO blog content pipeline with keyword research and optim....

The catch is that this lives in the "advanced" difficulty tier for a reason. You'll be working with API webhooks, conditional logic, and data transformation. But if you're serious about scaling video marketing across multiple markets, this workflow pays dividends immediately.

The Automated Workflow

Choosing Your Orchestration Tool

For this workflow, I recommend n8n. Here's why: it handles both webhook triggers and scheduled jobs cleanly, its built-in HTTP nodes work well with Hour One and Vidau AI's APIs, and its visual workflow builder makes debugging straightforward when something goes wrong. Zapier works too, but you'll hit automation limits faster. Make (formerly Integromat) is viable but introduces unnecessary complexity for this particular task.

The workflow follows this sequence:

  1. Trigger on webhook (script submission from your CMS)
  2. Generate video with Hour One
  3. Poll for completion
  4. Submit to Vidau AI for multilingual dubbing and subtitling
  5. Poll for completion
  6. Prepare final assets and generate metadata
  7. Trigger distribution workflows (webhook out to your publishing system)

Setting Up the Webhook Trigger

Your n8n workflow begins with a webhook node. This is where your content management system or marketing team submits the script.


POST /webhook/video-marketing-campaign
Content-Type: application/json

{
  "scriptId": "script-2024-001",
  "scriptText": "Welcome to our product. We believe in quality above all else...",
  "targetLanguages": ["es", "fr", "de", "ja", "pt"],
  "videoStyle": "professional",
  "duration": "30-seconds",
  "brandColour": "#2563eb",
  "outputFormats": ["youtube", "instagram", "tiktok"],
  "callbackUrl": "https://your-api.example.com/webhooks/video-complete"
}

In n8n, add a Webhook node and configure it to accept POST requests. Store the webhook URL for later; this is where external systems will submit jobs.

Generating Video with Hour One

Hour One's API accepts a script and returns a video ID. You'll poll that ID until the video is ready.

First, you need an Hour One API key. Get this from your Hour One dashboard and store it as an n8n environment variable called HOUR_ONE_API_KEY.

In n8n, add an HTTP Request node configured as follows:


Method: POST
URL: https://api.hourone.ai/video/generate
Headers:
  Authorization: Bearer YOUR_HOUR_ONE_API_KEY
  Content-Type: application/json

Body (JSON):
{
  "script": "{{ $json.scriptText }}",
  "avatar": "anna",
  "style": "{{ $json.videoStyle }}",
  "language": "en",
  "duration": "{{ $json.duration }}"
}

The response will include a videoId. Extract this immediately.

{
  "videoId": "video-abc123xyz",
  "status": "processing",
  "estimatedTime": 180
}

Polling Hour One Until Video Completion

Hour One videos take between 1 and 10 minutes to generate depending on length and complexity. Use n8n's Loop node paired with a Wait node to poll every 30 seconds.

Add a Loop node that repeats up to 20 times (10 minutes total). Inside the loop, add an HTTP Request node:


Method: GET
URL: https://api.hourone.ai/video/{{ $json.videoId }}/status
Headers:
  Authorization: Bearer YOUR_HOUR_ONE_API_KEY

Check the response status. If it's "completed", break the loop and continue. If it's still "processing", wait 30 seconds and loop again.

{
  "status": "completed",
  "videoUrl": "https://videos.hourone.ai/video-abc123xyz.mp4",
  "duration": 30,
  "resolution": "1920x1080"
}

Store the videoUrl for the next step.

Submitting to Vidau AI for Multilingual Processing

Now that you have the generated video, Vidau AI will dub it and create subtitles in all your target languages. This is where the real scaling happens.

Vidau AI accepts a video URL and returns a job ID. Set up an HTTP Request node:


Method: POST
URL: https://api.vidau.ai/v1/jobs
Headers:
  Authorization: Bearer YOUR_VIDAU_API_KEY
  Content-Type: application/json

Body (JSON):
{
  "videoUrl": "{{ $json.videoUrl }}",
  "sourceLanguage": "en",
  "targetLanguages": {{ $json.targetLanguages }},
  "options": {
    "includeDubbing": true,
    "includeSubtitles": true,
    "subtitleFormat": "vtt",
    "voiceProfile": "professional"
  },
  "callbackUrl": "https://your-n8n-instance.com/webhook/vidau-complete"
}

The response provides a job ID:

{
  "jobId": "job-vidau-2024-001",
  "status": "queued",
  "estimatedTime": 600
}

Polling Vidau AI Until Processing Complete

Similar to the Hour One polling, use another Loop node with 30-second waits. Vidau jobs can take 10 to 20 minutes depending on video length and language count.


Method: GET
URL: https://api.vidau.ai/v1/jobs/{{ $json.jobId }}
Headers:
  Authorization: Bearer YOUR_VIDAU_API_KEY

Check for status "completed".

{
  "jobId": "job-vidau-2024-001",
  "status": "completed",
  "outputs": {
    "es": {
      "videoUrl": "https://output.vidau.ai/video-es.mp4",
      "subtitleUrl": "https://output.vidau.ai/video-es.vtt"
    },
    "fr": {
      "videoUrl": "https://output.vidau.ai/video-fr.mp4",
      "subtitleUrl": "https://output.vidau.ai/video-fr.vtt"
    },
    "de": {
      "videoUrl": "https://output.vidau.ai/video-de.mp4",
      "subtitleUrl": "https://output.vidau.ai/video-de.vtt"
    },
    "ja": {
      "videoUrl": "https://output.vidau.ai/video-ja.mp4",
      "subtitleUrl": "https://output.vidau.ai/video-ja.vtt"
    },
    "pt": {
      "videoUrl": "https://output.vidau.ai/video-pt.mp4",
      "subtitleUrl": "https://output.vidau.ai/video-pt.vtt"
    }
  }
}

Asset Preparation and Distribution Trigger

Once Vidau completes, you have multi-language video assets ready. The final step transforms these into distribution-ready files and triggers your publishing workflow.

Add another HTTP Request node that sends everything to your distribution system:


Method: POST
URL: {{ $json.callbackUrl }}
Headers:
  Content-Type: application/json
  X-Webhook-Signature: sha256=YOUR_SIGNATURE_HERE

Body (JSON):
{
  "scriptId": "{{ $json.scriptId }}",
  "originalVideoUrl": "{{ $json.videoUrl }}",
  "multilingual": {
    "es": {
      "videoUrl": "{{ $json.outputs.es.videoUrl }}",
      "subtitleUrl": "{{ $json.outputs.es.subtitleUrl }}"
    },
    "fr": {
      "videoUrl": "{{ $json.outputs.fr.videoUrl }}",
      "subtitleUrl": "{{ $json.outputs.fr.subtitleUrl }}"
    },
    "de": {
      "videoUrl": "{{ $json.outputs.de.videoUrl }}",
      "subtitleUrl": "{{ $json.outputs.de.subtitleUrl }}"
    },
    "ja": {
      "videoUrl": "{{ $json.outputs.ja.videoUrl }}",
      "subtitleUrl": "{{ $json.outputs.ja.subtitleUrl }}"
    },
    "pt": {
      "videoUrl": "{{ $json.outputs.pt.videoUrl }}",
      "subtitleUrl": "{{ $json.outputs.pt.subtitleUrl }}"
    }
  },
  "outputFormats": {{ $json.outputFormats }},
  "completedAt": "{{ now().toISOString() }}"
}

This callback triggers your downstream publishing system, which might handle YouTube uploads, Instagram Reels formatting, TikTok distribution, and so on. Keeping that separate maintains architectural clarity; video generation and distribution are distinct concerns.

Complete n8n Workflow Structure

Your full workflow in n8n should look like this:

  1. Webhook Trigger (listens for POST)
  2. HTTP Request: Hour One Generate
  3. Loop with HTTP Request: Hour One Status Check
  4. HTTP Request: Vidau AI Submit Job
  5. Loop with HTTP Request: Vidau AI Status Check
  6. HTTP Request: Trigger Distribution Webhook
  7. Email Node: Send completion notification (optional, but useful for oversight)

Each node passes data to the next using n8n's native variable syntax: {{ $json.fieldName }}. This keeps everything in one place and eliminates manual data entry.

The Manual Alternative

If you prefer more control over each step, you can use Claude Code to orchestrate this directly. You'd write a script that calls Hour One and Vidau AI sequentially, handling polling yourself.

import requests
import time
import json
from datetime import datetime

def generate_video_with_hour_one(script_text, style="professional"):
    headers = {
        "Authorization": f"Bearer {HOUR_ONE_API_KEY}",
        "Content-Type": "application/json"
    }
    payload = {
        "script": script_text,
        "avatar": "anna",
        "style": style,
        "language": "en",
        "duration": "30-seconds"
    }
    
    response = requests.post(
        "https://api.hourone.ai/video/generate",
        headers=headers,
        json=payload
    )
    response.raise_for_status()
    return response.json()["videoId"]

def poll_hour_one_status(video_id, max_attempts=20, wait_seconds=30):
    headers = {
        "Authorization": f"Bearer {HOUR_ONE_API_KEY}"
    }
    
    for attempt in range(max_attempts):
        response = requests.get(
            f"https://api.hourone.ai/video/{video_id}/status",
            headers=headers
        )
        response.raise_for_status()
        data = response.json()
        
        if data["status"] == "completed":
            return data["videoUrl"]
        
        print(f"Attempt {attempt + 1}: Still processing, waiting {wait_seconds}s...")
        time.sleep(wait_seconds)
    
    raise TimeoutError(f"Hour One video {video_id} did not complete within {max_attempts * wait_seconds} seconds")

def submit_to_vidau(video_url, target_languages):
    headers = {
        "Authorization": f"Bearer {VIDAU_API_KEY}",
        "Content-Type": "application/json"
    }
    payload = {
        "videoUrl": video_url,
        "sourceLanguage": "en",
        "targetLanguages": target_languages,
        "options": {
            "includeDubbing": True,
            "includeSubtitles": True,
            "subtitleFormat": "vtt"
        }
    }
    
    response = requests.post(
        "https://api.vidau.ai/v1/jobs",
        headers=headers,
        json=payload
    )
    response.raise_for_status()
    return response.json()["jobId"]

def poll_vidau_status(job_id, max_attempts=40, wait_seconds=30):
    headers = {
        "Authorization": f"Bearer {VIDAU_API_KEY}"
    }
    
    for attempt in range(max_attempts):
        response = requests.get(
            f"https://api.vidau.ai/v1/jobs/{job_id}",
            headers=headers
        )
        response.raise_for_status()
        data = response.json()
        
        if data["status"] == "completed":
            return data["outputs"]
        
        print(f"Attempt {attempt + 1}: Still processing, waiting {wait_seconds}s...")
        time.sleep(wait_seconds)
    
    raise TimeoutError(f"Vidau job {job_id} did not complete within {max_attempts * wait_seconds} seconds")

def main(script_text, target_languages):
    print(f"[{datetime.now()}] Starting video generation workflow...")
    
    video_id = generate_video_with_hour_one(script_text)
    print(f"[{datetime.now()}] Hour One job created: {video_id}")
    
    video_url = poll_hour_one_status(video_id)
    print(f"[{datetime.now()}] Hour One completed: {video_url}")
    
    job_id = submit_to_vidau(video_url, target_languages)
    print(f"[{datetime.now()}] Vidau job created: {job_id}")
    
    outputs = poll_vidau_status(job_id)
    print(f"[{datetime.now()}] Vidau completed with {len(outputs)} language variants")
    
    return {
        "originalVideo": video_url,
        "multilingual": outputs,
        "completedAt": datetime.now().isoformat()
    }

if __name__ == "__main__":
    result = main(
        script_text="Welcome to our product. We believe in quality above all else...",
        target_languages=["es", "fr", "de", "ja", "pt"]
    )
    print(json.dumps(result, indent=2))

This approach gives you more debugging visibility and the ability to add custom logic (error recovery, asset validation, etc.) between steps. The downside is you're managing infrastructure, monitoring, and scaling yourself. Use this if your volume is low or you need hyper-specific customisation.

Pro Tips

Error Handling and Retries

Both Hour One and Vidau AI can fail for transient reasons: rate limits, temporary service outages, or network hiccups. In n8n, use the "Error Workflow" feature to handle failed nodes. Create a separate error workflow that logs failures to a database and optionally sends alerts. For critical jobs, implement exponential backoff: wait 5 seconds, then 10 seconds, then 20 seconds before retrying.

Rate Limiting Considerations

Hour One and Vidau AI both have rate limits. Hour One typically allows 10 concurrent generations; Vidau AI allows 5. If you're running this at scale (dozens of videos per day), queue jobs in a database rather than triggering them all at once. n8n's built-in scheduling can help; set your webhook workflow to run on a schedule that respects these limits.

Cost Optimisation Through Batching

If you're producing multiple videos, batch submissions to Vidau AI. Instead of sending five separate jobs (one per language), send all target languages in a single Vidau job. This reduces API calls and often qualifies for volume discounts. Both services reward batch efficiency.

Monitoring and Logging

Add logging at each major step. In n8n, use the "Set" node to capture timestamps and interim results. This creates an audit trail and makes debugging much faster when something goes wrong. Store these logs somewhere queryable; a simple PostgreSQL database works fine.

Handling API Changes

Both Hour One and Vidau AI are actively developing their products. Subscribe to their API changelog and set a quarterly reminder to review your integration. API versioning protects you from breaking changes, so explicitly specify API versions in your HTTP headers when available.

Cost Breakdown

ToolPlan NeededMonthly CostNotes
Hour OneProfessional£199Includes 100 video generations/month; £1.99 per additional video
Vidau AIGrowth£299Includes 500 minutes of video processing/month; includes dubbing and subtitles
n8nProfessional£240Includes 2,000 workflow executions/month; adequate for 50+ videos/month
TotalCombined£738Supports ~50 video campaigns monthly with all languages

If you're producing fewer than 10 videos per month, consider the Starter plans for Hour One (£49) and Vidau AI (£99), bringing total cost to around £389 with n8n. The scaling economics become attractive once you hit 30+ videos per month, at which point per-video costs drop significantly.

Remember these are base costs; actual spend depends on video length, number of languages, and whether you need premium voice profiles or custom avatars.

More Recipes