A TypeScript CLI application that generates AI-powered subtitles from YouTube videos using AssemblyAI Speech-to-Text API, built with the Effect framework.
- Bun runtime (latest stable version)
- AssemblyAI API key (free tier available)
- FFmpeg - Required for YouTube audio extraction and conversion
FFmpeg is essential for converting YouTube audio to the WAV format required by AssemblyAI Speech-to-Text API.
macOS:
# Using Homebrew (recommended)
brew install ffmpeg
# Or download from official site
# https://ffmpeg.org/download.html#build-macWindows:
# Using Windows Package Manager
winget install ffmpeg
# Or download from official site
# https://ffmpeg.org/download.html#build-windowsLinux:
# Ubuntu/Debian
sudo apt update && sudo apt install ffmpeg
# RHEL/CentOS/Fedora
sudo yum install ffmpeg
# or
sudo dnf install ffmpeg- Clone the repository and install dependencies:
bun install- The postinstall script will automatically download yt-dlp binary.
Create a .env file in the project root or set the following environment variables:
# AssemblyAI API Key
ASSEMBLYAI_KEY=your_assemblyai_api_key_here- Go to the AssemblyAI website
- Sign up or log in.
- Navigate to your dashboard or API settings to find your API key.
- Set the
ASSEMBLYAI_KEYenvironment variable.
# Process a YouTube video and generate subtitles
bun run dev "https://www.youtube.com/watch?v=VIDEO_ID"[
{
"id": 0,
"value": "Welcome to this tutorial on Effect framework.",
"startTimeMs": 1200,
"endTimeMs": 4800,
"score": 0.92
},
{
"id": 1,
"value": "Today we'll learn about functional programming.",
"startTimeMs": 5000,
"endTimeMs": 8500,
"score": 0.87
}
]# Using npm-style scripts
bun run dev <youtube-url>
bun run start <youtube-url>To run the unit and integration tests:
bun testTo run the linter and check for code style issues:
bun run lintThis application demonstrates advanced Effect framework patterns:
- Service Architecture: Services defined using
Context.Tagfor dependency injection - Layer Composition: Modular layer composition with
Layer.mergeAll - Error Handling: Tagged error types using
Data.TaggedError - Configuration: Environment variables managed with
Configmodule - Resource Management: Automatic cleanup using
Effect.acquireRelease - Schema Validation: Type-safe data validation with
@effect/schema
- YouTubeDownloader: Extracts audio streams from YouTube URLs using yt-dlp
- Transcription: Processes audio through AssemblyAI API
- FileSystemService: Manages temporary file creation and cleanup
- AssemblyAIConfigService: Handles API configuration from environment
- Input Validation: YouTube URL validated and parsed
- Audio Extraction: Video downloaded and converted to WAV format
- Speech Recognition: Audio processed through AssemblyAI
- Output Generation: Results formatted as JSON array of
SubtitleTokenobjects
- Cause: Invalid YouTube URL or video not accessible
- Solutions:
- Check URL format:
https://www.youtube.com/watch?v=VIDEO_ID - Ensure video is public and not age-restricted
- Try a different video
- Check URL format:
- Cause: FFmpeg is not installed or not available in system PATH
- Solutions:
- Install FFmpeg using the instructions in Prerequisites section
- Restart your terminal after installation
- Verify installation:
ffmpeg -version - On macOS, ensure Homebrew's bin directory is in your PATH
- Cause: yt-dlp audio extraction problems or FFmpeg conversion failures
- Solutions:
- Ensure FFmpeg is properly installed and accessible
- Application automatically converts to WAV format required by AssemblyAI
- Check video accessibility (not private/age-restricted)
- Cause: Network connectivity or API rate limits
- Solution:
- Check internet connection
- Verify AssemblyAI API quotas
- Wait and retry for rate limit issues
Set environment variable for more detailed logging:
DEBUG=1 bun run dev <youtube-url>Verify all dependencies are installed:
bun install --verboseIf you encounter permission errors:
chmod +x ./yt-dlp- Runtime: Bun (ESNext modules)
- Language: TypeScript (strict mode)
- Framework: Effect with functional programming patterns
- Audio Processing: yt-dlp → WAV conversion → AssemblyAI
- Output Format: JSON conforming to
SubtitleTokeninterface