Dreim Paper 만들기: Reddit 시를 위한 YouTube Shorts 파이프라인
I’m happy to translate the article for you, but I’ll need the actual text you’d like translated. Could you please paste the content (or the portions you want translated) here? I’ll keep the source link at the top exactly as you provided and preserve all formatting, markdown, and code blocks.
왜 이 글이 존재하는가
저는 Dreim Paper라는 프로젝트를 진행하고 있습니다. 이 프로젝트는 Reddit의 r/OCPoetry 커뮤니티에서 공유되는 시를 가져와 YouTube Shorts 형태로 변환합니다.
r/OCPoetry는 사람들이 원작을 공유하고 피드백을 주고받는 활발한 커뮤니티입니다. 매달 수천 편의 시가 게시되는데, 다듬어진 작품도 있고 거친 초안도 있으며 모두 진정성을 가지고 있습니다. 문제는 대부분의 게시물이 몇 시간 안에 사라져, 열두 명 정도만이 보고 아카이브에 묻힌다는 점입니다.
저는 AWS에서 AI 시스템을 구축하며 수년을 보냈고, 자동화된 콘텐츠 제작 도구가 급증하는 모습을 지켜봤습니다. 대부분의 자동화는 생성에 초점을 맞춥니다—AI를 이용해 스크립트, 내레이션, 시각 자료 등을 만드는 것이죠. 이는 괜찮지만, 실제 사람에 의해 이미 만들어진 작품을 발굴하고 확대하는 다른 접근법이 필요하다고 느꼈습니다.
그래서 Dreim Paper가 탄생했습니다. 이 프로젝트는 발견, 포맷팅, 녹음 등 번거로운 작업을 반자동 파이프라인으로 처리하면서도, 인간의 큐레이션과 창의성을 중심에 두고 있습니다.
현재 아키텍처
1. 주간 디스커버리 (Lambda + SNS)
Lambda 함수가 매주 실행되어 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)
)
이 함수는 SNS 토픽에 게시물을 발행하고, 그 결과로 시 ID, 제목, 작가, 내용이 포함된 JSON 페이로드를 이메일로 받아볼 수 있습니다.
2. 수동 큐레이션 (웹 UI)
JSON을 웹 인터페이스에 붙여넣으면, 시를 하나씩 손글씨 애니메이션 효과와 함께 표시합니다:
// Core handwriting effect
const animatePoem = (element, text) => {
element.style.animation = `handwriting ${duration}s steps(${text.length})`;
};
이 큐레이션 단계는 의도된 과정입니다. 모든 시가 포맷에 맞는 것은 아니며—길이가 너무 길거나, 너무 추상적이거나, 감동이 부족한 경우도 있습니다. 나는 방대한 콘텐츠 파이프라인을 만들려는 것이 아니라, 보다 선별된 갤러리를 만들고자 합니다.
3. 녹화 및 게시 (현재 수동)
현재 나는 다음과 같은 과정을 거칩니다:
- 시가 애니메이션되는 화면을 녹화
- 클립을 편집
- 적절한 출처 표시와 함께 YouTube에 업로드
- Reddit에서 작가에게 허가 요청
작동은 하지만, 시간이 많이 소요됩니다.
왜 n8n이 아닐까?
요즘 아이들 사이에서 n8n이 대세인 것 같습니다. 여러 단계를 연결하는 시각적 워크플로 편집기를 자체 호스팅한다는 아이디어는 꽤 매력적이죠. 하지만 저는 이미 Reddit에서 시를 가져와 DynamoDB에 저장하는 Lambda 함수를 설정해 두었기 때문에, SNS 발행 호출을 위한 몇 줄을 추가하는 것이 완전히 새로운 생태계를 배우는 것보다 더 합리적이었습니다.
솔직히 말해서, 저에게 가장 큰 장벽은 계정 설정과 인프라 오버헤드였습니다.
비슷한 사용 사례로 n8n을 사용하고 계신 분이 있다면, 이 접근 방식이 얼마나 효과적이었는지 매우 궁금합니다. 여기에는 느슨한 결합 vs. 긴밀한 결합 디자인 패턴이 숨어 있습니다—n8n은 구성 요소를 쉽게 교체할 수 있는 유연성을 제공하지만, AWS 서비스는 이미 그 생태계에 들어가 있을 때 더 긴밀한 통합을 제공합니다.
다음 단계: Puppeteer + FFmpeg + YouTube API
자연스러운 진화는 판단은 수동으로 유지하면서 기계적인 부분을 자동화하는 것입니다.
자동 녹화
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;
}
YouTube 업로드
const { google } = require('googleapis');
const fs = require('fs');
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;
}
작가에게 연락하기
Reddit DM을 자동화할 수도 있지만, 그건 옳지 않은 것 같습니다. 대신, 생성된 초안을 사용해 반자동으로 유지하려고 합니다:
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();
}
창작자와의 관계가 중요하므로, 여전히 직접 보내겠습니다.
The Visual Challenge
현재 사이트는 최소화된 형태—흰 배경에 검은 손글씨와 주변에 연필 쓰는 소리 효과만 있습니다. 개인적으로는 보는 것이 힐링이 되지만, 꽤 단조롭습니다.
YouTube Shorts는 시각 매체입니다. 저는 시 채널들이 동적인 배경, 키네틱 타이포그래피, 은은한 모션 그래픽, 그리고 시의 분위기에 맞는 색상 팔레트를 사용하는 것을 보았습니다. Dreim Paper의 다음 버전에서는 다음을 탐구할 예정입니다:
- 시의 분위기에 맞는 배경 텍스처 또는 그라디언트
- 텍스트를 방해하지 않으면서 깊이를 더하는 은은한 카메라 팬/줌
- 핵심 구절에 맞춰 나타나는 애니메이션 일러스트
- 향상된 사운드 디자인 (연필 쓰는 소리와 레이어된 분위기 음악)
이 모든 요소는 선택 사항이며 제가 직접 제어할 수 있어, 시 자체가 주인공이라는 핵심 아이디어는 유지됩니다.
TL;DR
- 문제: r/OCPoetry에 올라오는 훌륭한 시가 금방 사라진다.
- 해결책: 창작자를 존중하는 반자동 파이프라인 (발견 → 선별 → 녹화 → 게시)
- 현재 스택: AWS Lambda + SNS 로 발견, 수동 웹 UI 로 선별, 수동 화면 녹화 및 YouTube 업로드
- 미래 스택: Puppeteer + FFmpeg 로 자동 녹화, YouTube Data API 로 업로드, 반수동 아웃리치, 풍부한 시각 요소
c 배경, 빠른 전환, AI‑생성 이미지 같은 스타일이 참여도를 높이며, 솔직히 저도 꽤 매력적으로 느낍니다.
질문: 이 차별성을 잃지 않으면서 시각적 흥미를 어떻게 더할 수 있을까요?
고려 중인 옵션
1. 큐레이션된 배경 이미지
r/HeavyMind 또는 r/ImaginaryLandscapes 같은 아트 서브레딧에서 가져오기. 도전 과제:
- 라이선스 문제가 복잡해짐
- 저장소/대역폭 비용이 콘텐츠와 함께 증가
- 또 다른 큐레이션 복잡성 추가
2. 생성형 배경
p5.js 또는 Three.js를 사용해 추상적이고 방해되지 않는 애니메이션 만들기:
// 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);
});
}
전체 화면 모드 진입
전체 화면 모드 종료
모든 것을 자체적으로 포함시켜 권리 문제를 없앨 수 있음.
3. 최소주의 유지
단순함에 무게를 두는 것이 가치가 있을 수도 있음. 모든 콘텐츠가 감각적인 경험일 필요는 없음. 때로는 글이 숨 쉴 공간을 주는 것만으로 충분함.
아직 고민 중.
기술 스택 요약
- Backend: AWS Lambda (Python) 스크래핑을 위해
- 알림: SNS → Email
- Frontend: 큐레이션을 위한 맞춤형 웹 UI
- 예정: Puppeteer + FFmpeg 녹화를 위해
- 예정: YouTube Data API v3 업로드를 위해
다음 단계
- Puppeteer 녹화 파이프라인 구축
- YouTube API 통합
- 작가 홍보 워크플로우 설정
- 시각적 향상 실험
- 도구를 오픈소스화하여 다른 사람들이 유사한 프로젝트를 실행할 수 있게 할지도 모름
목표는 대규모 확장이 아닙니다. 좋은 글이 더 많은 사람들에게 닿을 수 있는 작은 공간을 만드는 것입니다. 진행 과정을 함께하고 싶거나 시각적 방향에 대한 아이디어가 있다면 언제든지 알려 주세요.
Links
- r/OCPoetry
Matthew는 DREIM에서 창의적인 소프트웨어를 개발하는 소프트웨어 엔지니어입니다. 이전에 AWS에서 5년 동안 AI/ML 시스템을 작업했습니다. 현재는 예술가들을 지원하고 연결을 촉진하는 프로젝트에 집중하고 있습니다.