This is Part II of the faceless channel guide. In Part I, we covered the full workflow — generating music with Suno, creating visuals with Google Flow, and distributing with DistroKid.
But there's a bottleneck. Every time you finish a video, you have to manually go to YouTube Studio, click upload, type a title, write a description, add tags, set a thumbnail, pick a category, and hit publish. Do that twice a week and it gets old fast.
Let's automate it.
The Problem: Manual Uploading Doesn't Scale
If you're releasing 1-2 videos per week, that's 100+ uploads a year. Each one takes 10-15 minutes of clicking around YouTube Studio. That's 25+ hours a year spent on something a script can do in seconds.
Worse, manual uploads introduce inconsistency. You forget tags, your descriptions vary, you skip scheduling. Automation fixes all of that.
The Solution: YouTube Data API + Python
Google provides a free API that lets you upload videos, set metadata, and schedule publishes — all programmatically. You write a script once, then every upload is a single command.
What you can automate:
- Video file upload
- Title, description, and tags
- Category and language
- Privacy status (public, unlisted, private)
- Scheduled publish time
- Thumbnail upload
- Playlist assignment
Step 1: Set Up Google Cloud Credentials
Before writing any code, you need API access.
- Go to the Google Cloud Console and create a new project
- Enable the YouTube Data API v3
- Create OAuth 2.0 credentials (Desktop application type)
- Download the
client_secrets.jsonfile
This is a one-time setup. The credentials file lets your script authenticate as your YouTube account.
Important: The YouTube Data API has a daily quota of 10,000 units. A single video upload costs about 1,600 units, so you can upload roughly 6 videos per day on the free tier. More than enough for a faceless channel.
Step 2: Install Dependencies
You need two Python packages:
pip install google-api-python-client google-auth-oauthlib
That's it. No frameworks, no complex setup.
Step 3: The Upload Script
Here's the core script structure. It reads a video file, sets the metadata, and uploads it to your channel.
import os
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]
def authenticate():
flow = InstalledAppFlow.from_client_secrets_file(
"client_secrets.json", SCOPES
)
credentials = flow.run_local_server(port=0)
return build("youtube", "v3", credentials=credentials)
def upload_video(youtube, file_path, title, description, tags):
body = {
"snippet": {
"title": title,
"description": description,
"tags": tags,
"categoryId": "10", # Music
},
"status": {
"privacyStatus": "public",
"selfDeclaredMadeForKids": False,
},
}
media = MediaFileUpload(file_path, resumable=True)
request = youtube.videos().insert(
part="snippet,status",
body=body,
media_body=media,
)
response = request.execute()
print(f"Uploaded: https://youtu.be/{response['id']}")
return response
youtube = authenticate()
upload_video(
youtube,
file_path="output/midnight-rain.mp4",
title="Midnight Rain — Lofi Ambient",
description="A late-night ambient track for focus and calm.",
tags=["lofi", "ambient", "chill", "focus music"],
)
Run this once and it opens a browser for Google sign-in. After that first auth, you can save the token and skip the login on future uploads.
Step 4: Batch Uploads with a Config File
Typing metadata into the script every time defeats the purpose. Instead, use a simple JSON config file for each batch of uploads.
{
"uploads": [
{
"file": "output/midnight-rain.mp4",
"title": "Midnight Rain — Lofi Ambient",
"description": "A late-night ambient track for focus and calm.\n\nMade with Suno + Google Flow.\n\n#lofi #ambient #focusmusic",
"tags": ["lofi", "ambient", "chill", "focus music"],
"scheduled": "2026-03-01T14:00:00Z"
},
{
"file": "output/neon-drift.mp4",
"title": "Neon Drift — Synthwave",
"description": "Retro synthwave vibes for late-night drives.\n\nMade with Suno + Google Flow.\n\n#synthwave #retro #nightdrive",
"tags": ["synthwave", "retro", "electronic"],
"scheduled": "2026-03-04T14:00:00Z"
}
]
}
Then your script reads this file and uploads everything in sequence:
import json
with open("upload-batch.json") as f:
batch = json.load(f)
for video in batch["uploads"]:
upload_video(
youtube,
file_path=video["file"],
title=video["title"],
description=video["description"],
tags=video["tags"],
)
print(f"Done: {video['title']}")
Batch-create on the weekend, fill out the JSON file, run the script. Your whole week of content uploads in under a minute.
Step 5: Auto-Generate Descriptions and Tags
You can take this one step further. Instead of writing descriptions manually, use an LLM to generate them from the track title and genre.
import anthropic
client = anthropic.Anthropic()
def generate_metadata(title, genre):
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=300,
messages=[{
"role": "user",
"content": f"Write a short YouTube description (3-4 lines) and 8 relevant tags for a {genre} music track titled '{title}'. Format as JSON with 'description' and 'tags' keys."
}]
)
return json.loads(message.content[0].text)
Now your workflow is: generate music, generate visuals, combine them, and let the script handle the title, description, tags, and upload. The only manual step left is quality control — listening to the track and making sure the video looks right.
Step 6: Add Thumbnail Generation
YouTube thumbnails matter, even for faceless channels. You can automate these too.
Option 1: Use an AI image generator (Midjourney, DALL-E, or Google Imagen) to create a thumbnail that matches your visual style. Prompt it with your track title and genre.
Option 2: Create a template in Figma or Canva and use a script to swap out the track title text. Same layout every time, just different text. This actually builds brand recognition faster.
Option 3: Extract a frame from your Google Flow video. Pick the most visually striking moment, export it as a 1280x720 image, and upload it as the thumbnail via the API:
youtube.thumbnails().set(
videoId=video_id,
media_body=MediaFileUpload("thumbnail.jpg")
).execute()
The Automated Pipeline
Here's what your workflow looks like once everything is wired up:
- Create — Generate tracks in Suno, visuals in Google Flow (still manual, still creative)
- Combine — Merge audio + video in your editor, export the final file
- Configure — Add the file and basic info to your
upload-batch.json - Run — Execute the script. It generates the description, tags, uploads the video, sets the thumbnail, and schedules the publish date
The creative work stays manual. The repetitive publishing work disappears.
What Else Can You Automate?
Once you have the YouTube API wired up, there are a few more things worth automating:
- Playlist management — Automatically add each upload to the right playlist based on genre or mood
- YouTube Shorts — Script that extracts a 30-60 second clip from each video, adds a title overlay, and uploads it as a Short
- Analytics tracking — Pull view counts and watch time weekly, dump it to a spreadsheet to track what's working
- Cross-posting — Use the TikTok and Instagram APIs to post the same clips to Reels and TikTok automatically
You don't need all of this on day one. Start with the upload script. Once that's running smoothly, add layers.
The Point
A faceless channel is a content machine. The creative part — making the music, choosing the visuals — should take most of your time. Everything after that should be automated.
One Python script and a JSON file turn 15 minutes of clicking into 10 seconds of running a command. Over a year, that's hours of your life back. Spend it making better music instead.
Read Part I if you haven't set up the channel yet.
Next up: In Part III, I show you how to automate the music creation step itself — using Claude's browser extension to drive Suno for you.