Membuat Video YouTube Shorts Otomatis dengan AI
Pendahuluan
YouTube Shorts menuntut konten singkat, menarik, dan konsisten. Membuatnya secara manual memakan waktu, terutama untuk riset topik, penulisan naskah, dan produksi visual. Tutorial ini memperkenalkan pipeline otomatis yang memanfaatkan layanan AI (ChatGPT Plus, Claude Pro, Midjourney, Canva Pro) serta skrip Python untuk:
- Menghasilkan naskah yang SEO‑friendly.
- Membuat gambar/klip visual.
- Merender video 9:16 dengan ffmpeg.
- Mengupload langsung ke YouTube via API.
Arsitektur singkat:
User → Python CLI → (ChatGPT/Claude) → Script Text
↓
(Midjourney/Canva) → Visual Assets
↓
ffmpeg → .mp4 (Shorts)
↓
YouTube Data API → Upload
Prasyarat & Persiapan
| Item | Keterangan | Link |
|---|---|---|
| Akun Google Cloud & YouTube Data API | Untuk autentikasi upload | https://console.cloud.google.com/ |
| Python ≥3.9 | Bahasa utama | |
ffmpeg (CLI) |
Rendering video | https://ffmpeg.org/ |
| API key untuk ChatGPT Plus atau Claude Pro | Generate naskah | ChatGPT Plus • Claude Pro |
| API key untuk Midjourney atau Canva Pro | Generate gambar | Midjourney • Canva Pro |
google-auth, google-api-python-client |
Library Python | pip install google-auth google-auth-oauthlib google-api-python-client |
openai atau anthropic SDK |
Chat model client | pip install openai anthropic |
| Direktori kerja | ~/yt-shorts/ |
Instalasi dependensi
# Buat virtual environment
python -m venv venv
source venv/bin/activate
# Install paket Python
pip install openai anthropic google-auth google-auth-oauthlib google-api-python-client tqdm python-dotenv ffmpeg-python
Langkah Demi Langkah
Step 1 – Siapkan lingkungan & konfigurasi
- Buat file
.envdi root proyek:
```dotenv
# Chat model
OPENAI_API_KEY=your_chatgpt_plus_key
ANTHROPIC_API_KEY=your_claude_pro_key
# Image model
MIDJOURNEY_API_TOKEN=your_midjourney_token
CANVA_API_KEY=your_canva_pro_key
# YouTube
YOUTUBE_CLIENT_SECRETS=client_secret.json
YOUTUBE_REFRESH_TOKEN=your_refresh_token
2. Pastikan `ffmpeg` dapat dipanggil dari terminal:bash
ffmpeg -version
```
Step 2 – Generate naskah Shorts dengan AI
Gunakan ChatGPT Plus atau Claude Pro untuk membuat skrip 60‑detik (≈150 kata) yang mengandung keyword target.
# generate_script.py
import os, json, textwrap
from openai import OpenAI
from anthropic import Anthropic
def generate_prompt(topic):
return f"""Buat naskah YouTube Shorts berdurasi maksimal 60 detik tentang "{topic}".
- Sertakan hook 5 detik pertama.
- Gunakan bahasa Indonesia yang natural.
- Akhiri dengan call‑to‑action untuk subscribe.
- Tulis dalam format bullet point, tiap poin ≤ 20 kata."""
def get_script(topic):
# Pilih model yang tersedia
if os.getenv("OPENAI_API_KEY"):
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role":"user","content": generate_prompt(topic)}],
temperature=0.7,
)
return resp.choices[0].message.content.strip()
else:
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
resp = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=500,
temperature=0.7,
messages=[{"role":"user","content": generate_prompt(topic)}],
)
return resp.content[0].text.strip()
if __name__ == "__main__":
import sys
topic = sys.argv[1] if len(sys.argv) > 1 else "tips produktivitas kerja remote"
script = get_script(topic)
print(script)
Jalankan:
python generate_script.py "cara meningkatkan engagement di Instagram"
Output contoh:
- Hook: "Pernah penasaran kenapa postinganmu tidak pernah viral?"
- Gunakan hashtag relevan 3‑5 kali.
- Posting di jam 18.00 WIB, saat audience aktif.
- Tambahkan CTA: "Follow untuk trik selanjutnya!"
Step 3 – Buat visual dengan Midjourney atau Canva Pro
Berikut contoh fungsi Python yang memanggil Midjourney (via Discord bot API) atau Canva Pro (REST).
# generate_images.py
import os, requests, json, time
from pathlib import Path
def midjourney_generate(prompt, out_path):
# Placeholder: implement Discord bot request atau gunakan layanan pihak ketiga
raise NotImplementedError("Integrasi Midjourney via API belum publik; gunakan CLI atau bot Discord.")
def canva_generate(prompt, out_path):
url = "https://api.canva.com/v1/designs"
headers = {"Authorization": f"Bearer {os.getenv('CANVA_API_KEY')}"}
payload = {
"title": "Shorts Visual",
"description": prompt,
"template_id": "YOUR_TEMPLATE_ID", # pilih template 9:16
}
r = requests.post(url, headers=headers, json=payload)
r.raise_for_status()
design_id = r.json()["id"]
# Export PNG
export_url = f"https://api.canva.com/v1/designs/{design_id}/exports"
export_payload = {"format": "PNG", "size": "1080x1920"}
r = requests.post(export_url, headers=headers, json=export_payload)
r.raise_for_status()
download_url = r.json()["download_url"]
img_data = requests.get(download_url).content
Path(out_path).write_bytes(img_data)
if __name__ == "__main__":
import sys
prompt = sys.argv[1] if len(sys.argv) > 1 else "Ilustrasi futuristik tentang AI"
out_file = "assets/visual.png"
os.makedirs("assets", exist_ok=True)
canva_generate(prompt, out_file)
print(f"Gambar disimpan di {out_file}")
Catatan: Jika Anda memiliki akses ke Midjourney melalui API (beta), ganti fungsi
midjourney_generatedengan panggilan HTTP yang sesuai.
Step 4 – Render video Shorts dengan ffmpeg
Kita akan menggabungkan voiceover (TTS) dan visual menjadi video 9:16.
# render_shorts.py
import os, subprocess, textwrap
from gtts import gTTS # pip install gtts
from pathlib import Path
def tts_from_script(script, out_path):
tts = gTTS(text=script, lang='id')
tts.save(out_path)
def render_video(audio_path, image_path, output_path):
cmd = [
"ffmpeg",
"-y",
"-loop", "1",
"-i", image_path,
"-i", audio_path,
"-c:v", "libx264",
"-tune", "stillimage",
"-c:a", "aac",
"-b:a", "192k",
"-pix_fmt", "yuv420p",
"-shortest",
"-vf", "scale=1080:1920,format=yuv420p",
output_path,
]
subprocess.run(cmd, check=True)
if __name__ == "__main__":
script_file = "script.txt"
image_file = "assets/visual.png"
audio_file = "assets/voice.mp3"
output_video = "shorts.mp4"
# Simpan script ke file
with open(script_file, "w", encoding="utf-8") as f:
f.write(open("generated_script.txt","r").read())
# Generate voiceover
tts_from_script(open(script_file, "r", encoding="utf-8").read(), audio_file)
# Render final video
render_video(audio_file, image_file, output_video)
print(f"Video Shorts selesai: {output_video}")
Jalankan urutan:
python generate_script.py "cara meningkatkan engagement di Instagram" > generated_script.txt
python generate_images.py "Ilustrasi interaksi sosial di Instagram" # menghasilkan assets/visual.png
python render_shorts.py
Step 5 – Upload otomatis ke YouTube Shorts
Gunakan YouTube Data API v3. Pastikan OAuth 2.0 sudah di‑setup (client_secret.json) dan token disimpan.
# upload_youtube.py
import os, json, google.auth.transport.requests, google.oauth2.credentials
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]
def get_authenticated_service():
creds = google.oauth2.credentials.Credentials(
token=None,
refresh_token=os.getenv("YOUTUBE_REFRESH_TOKEN"),
token_uri="https://oauth2.googleapis.com/token",
client_id=json.load(open(os.getenv("YOUTUBE_CLIENT_SECRETS")))["installed"]["client_id"],
client_secret=json.load(open(os.getenv("YOUTUBE_CLIENT_SECRETS")))["installed"]["client_secret"],
scopes=SCOPES,
)
request = google.auth.transport.requests.Request()
creds.refresh(request)
return build("youtube", "v3", credentials=creds)
def upload_video(file_path, title, description, tags):
youtube = get_authenticated_service()
body = {
"snippet": {
"title": title,
"description": description,
"tags": tags,
"categoryId": "22", # People & Blogs
},
"status": {
"privacyStatus": "public",
"selfDeclaredMadeForKids": False,
},
}
media = MediaFileUpload(file_path, chunksize=-1, resumable=True, mimetype="video/mp4")
request = youtube.videos().insert(part="snippet,status", body=body, media_body=media)
response = None
while response is None:
status, response = request.next_chunk()
if status:
print(f"Upload progress: {int(status.progress()*100)}%")
print(f"Upload selesai, video ID: {response['id']}")
if __name__ == "__main__":
video_path = "shorts.mp4"
title = "Cara Meningkatkan Engagement di Instagram – 60 Detik Tips"
description = "Tips singkat tentang cara meningkatkan interaksi postingan Instagram Anda. Subscribe untuk konten AI & produktivitas."
tags = ["Instagram", "Engagement", "Tips", "AI", "Shorts"]
upload_video(video_path, title, description, tags)
Jalankan:
python upload_youtube.py
Tips Optimasi & Keamanan
| Area | Praktik Terbaik |
|---|---|
| API Keys | Simpan di .env, jangan hard‑code. Gunakan IAM role dengan hak minimum. |
| Prompt Engineering | Tambahkan instruksi “maks 150 kata” untuk menghindari teks terlalu panjang yang memicu TTS berlebih. |
| Resolusi Video | Shorts harus 1080×1920 (9:16). Pastikan gambar ber‑ratio yang sama untuk menghindari padding. |
| Rate Limiting | ChatGPT/Claude memiliki kuota harian; gunakan cache (Redis) untuk menyimpan script yang sudah dibuat. |
| Logging | Simpan log proses (script, image URL, video ID) ke file JSON untuk audit. |
| CI/CD | Integrasikan pipeline ke GitHub Actions dengan secret OPENAI_API_KEY, CANVA_API_KEY, dll. |
Troubleshooting Error Umum
| Error | Penyebab | Solusi |
|---|---|---|
openai.error.AuthenticationError |
API key tidak valid atau kadaluarsa. | Periksa nilai OPENAI_API_KEY di .env. Regenerate di dashboard ChatGPT Plus. |
ffmpeg: Invalid argument |
Resolusi atau codec tidak didukung. | Pastikan ffmpeg versi terbaru; gunakan -vf "scale=1080:1920" tepat. |
googleapiclient.errors.HttpError 403 |
Token OAuth tidak memiliki scope youtube.upload. |
Regenerate token dengan https://developers.google.com/oauthplayground dan pilih scope yang tepat. |
requests.exceptions.HTTPError 429 |
Rate limit pada Canva/Midjourney. | Tambahkan exponential backoff (time.sleep(2**retry)). |
FileNotFoundError: assets/visual.png |
Gambar tidak berhasil di‑download. | Verifikasi API key Canva, cek design_id dan pastikan template 9:16 tersedia. |
Kesimpulan
Dengan kombinasi **ChatGPT Plus / Claude Pro