Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
YouTube Security VideosGoogle Chrome: Unfinished Projects: Solange’s Public Sculpture(21.09.2026 um 17:02 Uhr)
Windows Tipps & SecurityBlurry or pixelated video in Microsoft Teams(21.09.2026 um 14:34 Uhr)
Sicherheitslücken (CVE)USN-8791-1: Ghostscript vulnerability(21.09.2026 um 14:51 Uhr)
Sicherheitslücken (CVE)USN-8792-1: Memcached vulnerability(21.09.2026 um 15:02 Uhr)
Sichere ProgrammierungI stopped rewriting the same Electron boilerplate — so I packaged it(21.09.2026 um 17:28 Uhr)
YouTube Security VideosGoogle Chrome: Unfinished Projects: Solange’s Public Sculpture(21.09.2026 um 17:02 Uhr)
Windows Tipps & SecurityBlurry or pixelated video in Microsoft Teams(21.09.2026 um 14:34 Uhr)
Sicherheitslücken (CVE)USN-8791-1: Ghostscript vulnerability(21.09.2026 um 14:51 Uhr)
Sicherheitslücken (CVE)USN-8792-1: Memcached vulnerability(21.09.2026 um 15:02 Uhr)
Sichere ProgrammierungI stopped rewriting the same Electron boilerplate — so I packaged it(21.09.2026 um 17:28 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How I Built a YouTube Shorts Brief Generator with PHP and the OpenAI API (in a Few Hours)

I've been building a YouTube Shorts automation engine as a side project — the kind of system that takes a niche, generates a script, hands it to a text-to-speech API, pairs it with stock footage, and uploads it automatically. The pipeline …

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

I've been building a YouTube Shorts automation engine as a side project — the kind of system that takes a niche, generates a script, hands it to a text-to-speech API, pairs it with stock footage, and uploads it automatically.



The pipeline itself is a bigger build. But one thing kept slowing me down at the start of every session: I'd sit down to test a new part of the system and realise I needed a decent script to feed into it. Writing one from scratch every time was killing momentum.



So I built a small tool to solve that problem. A few hours later I had something I actually wanted to use — and apparently other people did too.



Here's how I built it.









What the tool does



You give it a niche and a topic. It gives you back a complete YouTube Shorts brief:





  • Hook — one punchy line, max 12 words, engineered to stop the scroll


  • Script — 45–60 seconds spoken, conversational, with a built-in insight and soft CTA


  • B-roll notes — 4 specific visual suggestions matched beat-for-beat to the script


  • Caption — under 150 characters, copy-paste ready


  • Hashtags — 8 tags, mix of high-volume and niche-specific



The whole thing runs on PHP, calls the OpenAI API server-side, and sits behind a Stripe credit system.









The stack




  • PHP 8.x (already on my shared hosting)

  • Bootstrap 5 for the frontend

  • OpenAI gpt-4o-mini — cheap, fast, good enough

  • Stripe Payment Links + webhooks

  • PHPMailer for transactional email

  • MySQL for user and credit storage



Nothing exotic. Deliberately so — I wanted something I could deploy to shared hosting without touching a terminal.









The prompt engineering



This is where most of the actual work happened. Getting the model to return clean, consistently structured output without preamble or markdown took more iteration than the code did.



The final system prompt:




You are an expert YouTube Shorts scriptwriter.

Your job is to generate a complete, ready-to-publish YouTube Shorts brief.

Return ONLY the following structure, with NO preamble, no commentary, no markdown formatting:

🪝 HOOK
[One punchy spoken line that stops the scroll. Use curiosity, shock, or a bold claim. Max 12 words.]

📝 SCRIPT
[Natural, conversational script for 45-60 seconds spoken. No jargon. Short sentences.
Each line flows into the next. Include one surprising fact or insight.
End with a soft CTA like "follow for more" or "comment below."]

🎬 B-ROLL
[4 specific visual suggestions that match the script beat by beat. Be precise —
not "show a phone" but "close-up of ChatGPT interface generating a response in real time."]

📣 CAPTION
[One punchy caption under 150 characters with a hook and 2-3 relevant emojis.]

#️⃣ HASHTAGS
[8 hashtags — mix of high volume and niche specific. One per line. No spaces between words.]






The key things that made it work:





  1. "Return ONLY" — without this you get preamble every time


  2. Emoji section headers — made parsing reliable and consistent


  3. Negative examples in the B-roll instruction — telling it what not to do ("not 'show a phone' but...") produced dramatically more specific output


  4. Word limits on the hook — "max 12 words" was enforced much better than "short"









The PHP backend



The frontend posts to generate.php, which handles the OpenAI call server-side so the API key never touches the browser:




$payload = json_encode([
'model' => 'gpt-4o-mini',
'max_tokens' => 1000,
'messages' => [
['role' => 'system', 'content' => $system_prompt],
['role' => 'user', 'content' => "Niche: {$niche}\nTopic: {$topic}\nTone: {$tone}"],
]
]);

$ch = curl_init('https://api.openai.com/v1/chat/completions');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key,
],
CURLOPT_TIMEOUT => 30,
]);






Standard stuff. The response parsing just pulls $decoded['choices'][0]['message']['content'] and sends it back as JSON.









Parsing the output on the frontend



Since the model returns consistent emoji-headed sections, parsing is straightforward:




function extract(text, startMarker, endMarker) {
const start = text.indexOf(startMarker);
if (start === -1) return '';
const afterMarker = text.indexOf('\n', start) + 1;
const end = endMarker ? text.indexOf(endMarker, afterMarker) : text.length;
return text.slice(afterMarker, end === -1 ? text.length : end).trim();
}

const sections = {
hook: extract(text, '🪝 HOOK', '📝 SCRIPT'),
script: extract(text, '📝 SCRIPT', '🎬 B-ROLL'),
broll: extract(text, '🎬 B-ROLL', '📣 CAPTION'),
caption: extract(text, '📣 CAPTION', '#️⃣ HASHTAGS'),
hashtags: extract(text, '#️⃣ HASHTAGS', null),
};






Each section renders into its own panel with a copy button.









The credit system



Initially I thought about selling lifetime access — £27 once, use it forever. Then I did the maths. gpt-4o-mini costs roughly £0.01 per generation. A heavy user could generate 1,000 briefs and cost me £10 on a one-time payment. Not sustainable.



Credit packs made more sense:




























Pack Credits Price
Starter 30 £7
Creator 100 £19
Operator 300 £47


Credits never expire. Users get an email alert when they drop to 10 remaining. Top-ups add to their existing balance via the same access link — no new account, no friction.



The MySQL table is simple:




CREATE TABLE `users` (
`token` CHAR(64) NOT NULL,
`email` VARCHAR(255) NOT NULL,
`credits` INT UNSIGNED NOT NULL DEFAULT 0,
`credits_used` INT UNSIGNED NOT NULL DEFAULT 0,
`low_credit_sent` TINYINT(1) NOT NULL DEFAULT 0,
UNIQUE KEY `token` (`token`),
KEY `email` (`email`)
);












The Stripe webhook gotcha



Stripe occasionally fires duplicate webhook events — either retries or genuine duplicates. The first version of the webhook used payment_intent as the idempotency key, which didn't catch all cases.



The fix was to use $session['id'] — the checkout session ID — which is always the same on retries, and back it up with a separate payments table with a unique constraint:




// Try to insert — unique constraint rejects duplicates
try {
$pdo->prepare('
INSERT INTO payments (payment_intent, email, pack, credits_added)
VALUES (?, ?, ?, ?)
'
)->execute([$session_id, $buyer_email, $pack_key, $credits_to_add]);
} catch (\PDOException $e) {
// Already processed — return 200 silently
http_response_code(200);
exit;
}






The whole credit update runs inside a transaction. If two requests race past the initial check simultaneously

, only one can insert into payments. The other hits the unique constraint and exits without touching credits.









What I'd do differently



Use a queue for webhook processing. On shared hosting, if the webhook takes more than a few seconds Stripe retries it. A job queue would let you return 200 immediately and process in the background — cleaner than relying purely on idempotency keys.



Add usage analytics from day one. I can see total credits used per user but I have no visibility into which niches or topics are generating the most briefs. That data would be useful for marketing.



Test the email earlier. PHP's mail() is unreliable on shared hosting. I switched to PHPMailer with SMTP on day two — should have started there.









The result



Tool Input Screenshoot



Tool Output SCreenshot



The tool is live at https://creator.buizy.io



If you're building a faceless YouTube channel or a Shorts automation pipeline and want to stop writing briefs by hand, it's £7 to try.



If you're a developer building something similar, hopefully the prompt structure and idempotency approach save you a few hours of head-scratching.



Happy to answer questions in the comments.






Built with PHP, OpenAI, Stripe, and too much coffee.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How I Built a YouTube Shorts Brief Generator with PHP and the OpenAI API (in a Few Hours)

Thematisch verwandte Begriffe: Built, YouTube, Shorts, Brief · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-94393 | When a user creates or edits a report inside an event, MISP can identify…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick