DEV Community

Matthew Reid
Matthew Reid

Posted on

Building Dreim Paper: A YouTube Shorts Pipeline for Reddit Poetry

Why This Exists

I've been working on a project called Dreim Paper that takes poetry from Reddit's r/OCPoetry community and turns it into YouTube Shorts.

r/OCPoetry is a thriving community where people share original work and provide feedback. Thousands of poems are posted monthly—some polished, some raw, all genuine. The problem is most of these posts get buried after a few hours, seen by maybe a dozen people before disappearing into the archive.

I spent years at AWS building AI systems, and I've watched the explosion of automated content creation tools. Most of the automation I see is focused on generation—using AI to create scripts, narration, visuals, everything. That's fine, but it felt like there was space for a different approach: using automation to surface and amplify work that already exists, created by real people.

So that's what Dreim Paper does. It's a semi-automated pipeline that handles the tedious parts—discovery, formatting, recording—while keeping human curation and human creativity at the center.

Current Architecture

1. Weekly Discovery (Lambda + SNS)

A Lambda function runs weekly to scrape new posts from r/OCPoetry:

# Simplified example
def lambda_handler(event, context):
    poems = scrape_new_poems()

    sns_client.publish(
        TopicArn=SNS_TOPIC_ARN,
        Subject="Weekly Poetry Digest",
        Message=json.dumps(poems, indent=2)
    )
Enter fullscreen mode Exit fullscreen mode

The function publishes to an SNS topic, which emails me a JSON payload with poem IDs, titles, authors, and content.

2. Manual Curation (Web UI)

I paste the JSON into a web interface that displays poems one at a time with a handwriting animation effect:

// Core handwriting effect
const animatePoem = (element, text) => {
  element.style.animation = `handwriting ${duration}s steps(${text.length})`;
};
Enter fullscreen mode Exit fullscreen mode

This curation step is intentional. Not everything works for the format—some poems are too long, some too abstract, some just don't resonate. I'm not trying to build a firehose of content; I'm trying to build something more like a curated gallery.

3. Recording & Publishing (Currently Manual)

Right now I'm:

  • Recording my screen as the poem animates
  • Editing the clips
  • Uploading to YouTube with proper attribution
  • Reaching out to authors on Reddit for permission

It works, but it's time-consuming.

Why Not n8n?

Seems like n8n is all the rage with the kids. The idea of self-hosting a visual workflow editor that chains a bunch of these steps sounds pretty alluring. But I already had a Lambda function set up to fetch the poems from Reddit and write them to DDB, so adding a few lines for the SNS publishing call seemed more reasonable than learning an entirely new ecosystem. Honestly one of the biggest hurdles for me is just the account setup and infrastructure overhead.

But if anyone reading this uses n8n for a similar use case, I'd be very curious how effective this approach has been. There's a loose vs tight coupling architecture design pattern buried in here somewhere—n8n gives you flexibility to swap components easily, but AWS services give you tighter integration when you're already in that ecosystem.

The Next Steps: Puppeteer + FFmpeg + YouTube API

The natural evolution is to automate the mechanical parts while keeping the judgment manual.

Automated Recording

const puppeteer = require('puppeteer');
const ffmpeg = require('fluent-ffmpeg');

async function recordPoem(poemData) {
  const browser = await puppeteer.launch({
    headless: false,
    args: ['--window-size=1080,1920'] // Vertical format
  });

  const page = await browser.newPage();
  await page.goto(`https://dreimpaper.com/poem/${poemData.id}`);

  // Start recording with ffmpeg
  const videoPath = `./videos/${poemData.id}.mp4`;
  const ffmpegProcess = startRecording(videoPath);

  // Wait for animation
  await page.waitForTimeout(poemData.duration * 1000);

  ffmpegProcess.kill();
  await browser.close();

  return videoPath;
}
Enter fullscreen mode Exit fullscreen mode

YouTube Upload

const { google } = require('googleapis');

async function uploadToYouTube(videoPath, poemData) {
  const youtube = google.youtube('v3');

  const response = await youtube.videos.insert({
    part: 'snippet,status',
    requestBody: {
      snippet: {
        title: `"${poemData.title}" by u/${poemData.author}`,
        description: `Original poem by u/${poemData.author} from r/OCPoetry\n\nRead more at: ${poemData.redditUrl}`,
        tags: ['poetry', 'original poetry', 'spoken word'],
      },
      status: { privacyStatus: 'public' }
    },
    media: { body: fs.createReadStream(videoPath) }
  });

  return response.data;
}
Enter fullscreen mode Exit fullscreen mode

Author Outreach

I could automate Reddit DMs, but that feels wrong. Instead, planning to keep this semi-manual with generated drafts:

function generateOutreachMessage(author, poemTitle, videoUrl) {
  return `
Hi u/${author},

I came across your poem "${poemTitle}" on r/OCPoetry and found it really moving.

I run a project that shares poetry from the community. I recorded your poem and posted it here: ${videoUrl}

If you'd prefer I take it down, just let me know—no hard feelings. Otherwise, hope you enjoy seeing your work in this format!

Best,
Matt
  `.trim();
}
Enter fullscreen mode Exit fullscreen mode

The relationship with the creator matters, so I'll still send these manually.

The Visual Challenge

Right now the site is minimal—white background, black text handwriting with an ambient pencil writing sound effect. I personally find it cathartic to watch, but it's pretty plain.

YouTube Shorts are a visual medium. I've seen poetry channels using dynamic backgrounds, rapid transitions, AI-generated imagery. That style gets engagement, and honestly, I find it pretty captivating too.

The question is: how do I add visual interest without losing what makes this different?

Options I'm Considering:

1. Curated Background Images
Pull from art subreddits like r/HeavyMind or r/ImaginaryLandscapes. Challenges:

  • Licensing gets murky
  • Storage/bandwidth costs scale with content
  • Adds another layer of curation complexity

2. Generative Backgrounds
Use p5.js or Three.js for abstract, non-distracting animations:

// Simple particle system
function draw() {
  particles.forEach(p => {
    p.x += sin(frameCount * 0.01) * 0.5;
    p.y += cos(frameCount * 0.01) * 0.5;
    ellipse(p.x, p.y, 2);
  });
}
Enter fullscreen mode Exit fullscreen mode

Keeps everything self-contained, no rights issues.

3. Stay Minimal
Maybe there's value in leaning into simplicity. Not every piece of content needs to be a sensory experience. Sometimes letting the words breathe is enough.

Still figuring this out.

Tech Stack Summary

  • Backend: AWS Lambda (Python) for scraping
  • Notifications: SNS → Email
  • Frontend: Custom web UI for curation
  • Planned: Puppeteer + FFmpeg for recording
  • Planned: YouTube Data API v3 for uploads

What's Next

  • Build the Puppeteer recording pipeline
  • Integrate YouTube API
  • Set up the author outreach workflow
  • Experiment with visual enhancements
  • Maybe open-source the tooling so others can run similar projects

The goal isn't massive scale. It's about creating a small space where good writing can reach a few more people. If you're interested in following along or have ideas for the visual direction, I'd love to hear from you.


Links:


Matthew is a software engineer building creative software at DREIM. Previously spent 5 years at AWS working on AI/ML systems. Now focused on projects that serve artists and foster connection.

Top comments (0)