From Idea to Reality: The Birth of Fokus 🚀
You know that feeling when you watch a YouTube video and think "this would make an amazing short"? That's exactly where Fokus started. My friend and I were discussing how time-consuming it is for creators to repurpose their long-form content into shorts for platforms like TikTok, Instagram Reels, and YouTube Shorts. We thought: "What if we could automate this?"
That's how we started building Fokus, a platform that not only identifies the most engaging moments in YouTube videos but also adds customizable, dynamic captions that make your shorts stand out. Let me take you through our technical journey.
Technical Stack: Why We Chose What We Chose 🛠️
The Foundation: Next.js + shadcn/ui
We built Fokus using Next.js 13 (with the app router) and shadcn/ui components. Here's why:
// pages/app/dashboard/page.tsx
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
export default function Dashboard() {
return (
<Card className="p-6">
<h1 className="text-3xl font-bold">Your Videos</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{/* Video grid implementation */}
</div>
</Card>
)
}
Using shadcn/ui has been a game-changer for us. Instead of building everything from scratch, we could focus on what makes Fokus unique - the video processing and caption customization features.
Database Architecture with Prisma ⚡
One of our early decisions was using Prisma with our own database service. Here's a simplified version of our schema:
// prisma/schema.prisma
model Video {
id String @id @default(cuid())
youtubeUrl String
timestamps Timestamp[]
captions Caption[]
b_roll B_Roll[]
scheduledUploads ScheduledUpload[]
createdAt DateTime @default(now())
}
model Caption {
id String @id @default(cuid())
text String
style Json
videoId String
video Video @relation(fields: [videoId], references: [id])
}
model B_Roll {
id String @id @default(cuid())
timestamp Float
category String
sourceUrl String
videoId String
video Video @relation(fields: [videoId], references: [id])
}
model ScheduledUpload {
id String @id @default(cuid())
videoId String
platform String
scheduledFor DateTime
status String
video Video @relation(fields: [videoId], references: [id])
}
Core Features and Implementation ✨
Smart Moment Detection 🎯
One of the coolest features we built is our smart moment detection system. It analyzes factors like:
- Speech density and pace
- Musical transitions
- Scene changes
- Audience retention data (when available)
interface DetectionResult {
timestamp: number;
confidence: number;
type: 'speech' | 'music' | 'scene_change';
}
async function analyzeVideo(videoId: string): Promise<DetectionResult[]> {
// Our actual implementation is more complex, but you get the idea
const video = await prisma.video.findUnique({
where: { id: videoId },
include: { timestamps: true }
});
// Analysis logic here
return results;
}
Automated B-Roll Integration 🎬
One of our most powerful features is the automated B-roll system. It intelligently selects and inserts relevant B-roll footage based on the video content:
interface B_RollMatch {
timestamp: number;
keywords: string[];
context: string;
}
async function suggestB_Roll(videoId: string): Promise<B_RollMatch[]> {
const video = await prisma.video.findUnique({
where: { id: videoId },
include: { captions: true }
});
// AI-powered content analysis to identify B-roll opportunities
const contentAnalysis = await analyzeVideoContent(video);
// Match with our B-roll library
const suggestions = await matchB_RollContent(contentAnalysis);
return suggestions;
}
Caption Customization 🎨
We wanted to make caption customization both powerful and intuitive. Users can:
- Change fonts, colors, and animations
- Add emojis and effects
- Adjust timing and positioning
- Edit the actual text for better impact
Smart Upload Scheduling 📅
We implemented a sophisticated scheduling system that allows creators to plan their content distribution across multiple platforms:
interface UploadSchedule {
videoId: string;
platform: 'youtube_shorts' | 'tiktok' | 'instagram';
scheduledTime: Date;
options: UploadOptions;
}
async function scheduleUpload(schedule: UploadSchedule) {
// Create scheduled upload record
const scheduledUpload = await prisma.scheduledUpload.create({
data: {
videoId: schedule.videoId,
platform: schedule.platform,
scheduledFor: schedule.scheduledTime,
status: 'pending'
}
});
// Add to upload queue
await uploadQueue.add({
uploadId: scheduledUpload.id,
executeAt: schedule.scheduledTime
});
}
Challenges We Faced 💪
Performance Optimization
Processing video data can be heavy. We implemented a queue system using Bull to handle video processing:
import Queue from 'bull';
const videoQueue = new Queue('video-processing', {
redis: process.env.REDIS_URL
});
videoQueue.process(async (job) => {
const { videoId } = job.data;
// Process video and generate timestamps
});
Real-time Preview System
Getting the preview system right was tricky. We needed to balance performance with accuracy:
// components/PreviewPlayer.tsx
export function PreviewPlayer({ videoId, captions, b_roll }) {
const [currentTime, setCurrentTime] = useState(0);
const visibleCaptions = useMemo(() =>
captions.filter(cap =>
cap.startTime <= currentTime && cap.endTime >= currentTime
),
[captions, currentTime]
);
const currentB_Roll = useMemo(() =>
b_roll.find(clip =>
clip.timestamp <= currentTime && clip.timestamp + clip.duration >= currentTime
),
[b_roll, currentTime]
);
return (
<div className="relative">
<VideoPlayer
src={`/api/videos/${videoId}`}
onTimeUpdate={setCurrentTime}
/>
<CaptionOverlay captions={visibleCaptions} />
{currentB_Roll && <B_RollOverlay clip={currentB_Roll} />}
</div>
);
}
What's Next for Fokus? 🔮
We're working on some exciting features:
- Auto-translation into multiple languages
- Advanced AI-powered moment detection
- Custom animation builder
- Analytics dashboard for tracking performance
- Batch processing for multiple videos
- Enhanced B-roll library with AI-powered categorization
- Cross-platform analytics for scheduled uploads
Lessons Learned 📚
Building Fokus has taught us a lot:
- Start with a solid architecture, but be ready to adapt
- User feedback is gold - we've changed several features based on early user testing
- Performance optimization should be considered from day one
- Building with friends is fun, but clear communication is key
- Automation should enhance creativity, not replace it
Conclusion 🎬
Fokus represents our vision for the future of content creation, and we're excited to be actively building it. While still in development, it's already shaping up to be more than just a side project - it's our attempt to solve a real problem for content creators. By automating tedious tasks like B-roll selection and upload scheduling, we aim to help creators focus on what they do best: creating amazing content. We're currently in the final stages of development, continuously refining features based on early testing and feedback from fellow developers. We can't wait to share it with the creator community and see how they'll use it to transform their content creation workflow.