How to Build an End-to-End Script-to-Upload Pipeline with Claude and the API
Stitch script writing, metadata generation, captioning, and upload into one command that takes a topic and a video file.
Each earlier guide handled one step. This one connects them: given a topic and a finished MP4, a single command drafts a script for reference, generates the title and description, transcribes captions, uploads the video, and attaches the SRT. It is the assembly line for a one-person channel.
What you need
- Completed setup from the API key, upload, scripting, and captions guides
- An Anthropic API key and client_secret.json in the folder
- Whisper and ffmpeg installed
- A topic string and the path to your rendered MP4
Step 1: Outline the flow
The orchestrator calls helpers you already wrote. Keeping each step in its own function means one failure (say captions) does not lose the upload, and you can re-run a single stage.
Step 2: Generate metadata with Claude
Ask Claude for the title and description as JSON so the rest of the pipeline can use them without parsing prose.
import os, json, subprocess
from anthropic import Anthropic
from googleapiclient.http import MediaFileUpload
from upload import service # auth helper from the upload guide
ai = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
def metadata(topic):
msg = ai.messages.create(
model="claude-opus-4-5", max_tokens=600,
system="Return JSON {title (<60 chars), description}.",
messages=[{"role": "user", "content": f"Video topic: {topic}"}],
)
return json.loads(msg.content[0].text)Step 3: Caption, upload, and attach
Shell out to Whisper for the SRT, upload the video with the generated metadata, then insert the caption track against the new video id.
def run(topic, mp4):
meta = metadata(topic)
srt = mp4.rsplit(".", 1)[0] + ".srt"
subprocess.run(["whisper", mp4, "--model", "small",
"--output_format", "srt"], check=True)
yt = service()
body = {
"snippet": {"title": meta["title"],
"description": meta["description"], "categoryId": "22"},
"status": {"privacyStatus": "private"},
}
media = MediaFileUpload(mp4, chunksize=-1, resumable=True)
req = yt.videos().insert(part="snippet,status", body=body, media_body=media)
res = None
while res is None:
_, res = req.next_chunk()
vid = res["id"]
cap_body = {"snippet": {"videoId": vid, "language": "en",
"name": "English (Whisper)", "isDraft": False}}
yt.captions().insert(part="snippet", body=cap_body,
media_body=MediaFileUpload(srt, mimetype="application/octet-stream")).execute()
print("Live (private):", f"https://studio.youtube.com/video/{vid}/edit")
if __name__ == "__main__":
run("Fixing a wobbly chair in 10 minutes", "final.mp4")Result
A single command takes a topic and a file and returns a Studio link to a captioned, titled, private video ready for your final review. Wrap it in a loop over a folder and you have a true publishing assembly line.
Watch related tutorials
20:00
07:00
18:20
1:42:18
28:14
41:09