HomeTube uses a generic file naming system for temporary files to ensure resilience and independence from video titles. This allows the system to resume interrupted downloads and handle special characters or title changes gracefully.
TMP_DOWNLOAD_FOLDER/
└── youtube-{VIDEO_ID}/
├── url_info.json # Video metadata from yt-dlp
├── status.json # Download status and progress tracking
├── video-{FORMAT_ID}.{ext} # Downloaded video (e.g., video-399.mkv)
├── subtitles.{lang}.srt # Original subtitles (e.g., subtitles.en.srt)
├── subtitles-cut.{lang}.srt # Cut subtitles (e.g., subtitles-cut.en.srt)
├── session.log # Processing logs
└── final.{ext} # Final processed file (e.g., final.mkv)
yt-dlp requires a filename template for downloads. We use a pragmatic two-step approach:
-
Download with readable name (yt-dlp compatibility)
- yt-dlp uses the video title:
"My Video Title.mkv" - This is required by yt-dlp's
-ooption - Logs show meaningful names during download
- yt-dlp uses the video title:
-
Immediate rename to generic names (resilience)
- Video:
"My Video Title.mkv"→"video-399.mkv" - Subtitles:
"My Video Title.en.srt"→"subtitles.en.srt" - Atomic operation right after download completes
- Video:
-
Resume support (intelligent caching)
- Before downloading, check if
video-*.{ext}exists - If found, skip download and reuse existing file
- No re-download needed for interrupted processing
- Before downloading, check if
✅ yt-dlp Compatibility - Works naturally with yt-dlp's design
✅ Simple & Maintainable - Just rename operations, no complex hacks
✅ Readable Logs - Video titles visible during download
✅ Fast Resume - Instant detection of existing files
✅ Title Independence - Files work even if title changes
✅ Format Visibility - video-399.mkv shows format ID used
1. Download Request: "Amazing Video Tutorial"
📥 yt-dlp downloads as: "Amazing Video Tutorial.mkv"
2. Immediate Rename:
📦 "Amazing Video Tutorial.mkv" → "video-399.mkv"
📝 "Amazing Video Tutorial.en.srt" → "subtitles.en.srt"
📝 "Amazing Video Tutorial.fr.srt" → "subtitles.fr.srt"
3. Processing:
🎬 Cut video: "video-399.mkv" → "final.mkv"
📝 Cut subs: "subtitles.en.srt" → "subtitles-cut.en.srt"
4. Final Copy:
💾 "final.mkv" → "/videos/Amazing Video Tutorial.mkv"
(Original name from user input or video title)
The status.json file tracks download progress and completion:
{
"url": "https://youtube.com/watch?v=...",
"id": "abc123",
"title": "Amazing Video Tutorial",
"type": "video",
"downloaded_formats": [
{
"video_format": "399+251",
"subtitles": ["subtitles.en.srt", "subtitles.fr.srt"],
"filesize_approx": 41943040,
"status": "completed",
"actual_filesize": 41993040,
"downloaded_at": "2024-01-15T10:30:00Z"
}
],
"last_updated": "2024-01-15T10:30:00Z"
}This is used for:
- Tracking download progress across sessions
- Verifying file integrity after download
- Resume capability for interrupted downloads
- Tracking what video this temporary folder belongs to
- Resume support across sessions
- Format:
subtitles.{lang}.srt - Examples:
subtitles.en.srt,subtitles.fr.srt,subtitles.es.srt
- Format:
subtitles-cut.{lang}.srt - Examples:
subtitles-cut.en.srt,subtitles-cut.fr.srt - Created by
process_subtitles_for_cutting()
The subtitle search functions (find_subtitle_files_optimized) check in this order:
- Generic names (preferred):
subtitles.{lang}.srt - Video title names (legacy):
{video_title}.{lang}.srt - Other patterns:
{video_title}_{lang}.srt, etc.
This ensures compatibility with existing downloads.
video-{FORMAT_ID}.{ext}
video-399.mkv- Video format 399 in MKV containervideo-298.mp4- Video format 298 in MP4 containervideo-616.webm- Video format 616 in WebM container
The format ID comes from yt-dlp and indicates:
- Video resolution
- Codec used (AV1, VP9, H.264, etc.)
- Bitrate and quality level
This makes it easy to identify which format was actually downloaded.
final.{ext} - The processed file ready for copying
- If cutting: matches source extension (
.mkv,.mp4) - If not cutting: uses downloaded file extension
- WebM files are converted to MKV for better subtitle support
When moving to the final location (saves disk space):
- Use the filename from user input or video title
- Combine with file extension
- Move:
final.mkv→/videos/{filename}.mkv
✅ Generic files persist in tmp folder
✅ Next run detects video-*.{ext} and skips download
✅ Processing resumes from where it stopped
✅ Files are independent of video title
✅ Re-running with different title still works
✅ Filename from user input remains consistent
✅ No issues with Unicode, emojis, etc.
✅ Generic names are filesystem-safe
✅ User-provided filename used for final copy
✅ video-{FORMAT_ID}.{ext} is always preserved for future reuse
✅ final.{ext} is MOVED to destination (saves disk space, no duplicate)
✅ No automatic cleanup in normal workflow
✅ Manual cleanup available via configuration options
This ensures that:
- Re-downloading the same video skips download instantly
- Processing can be re-run without re-downloading
- Debugging is possible with all intermediate files available
✅ Clear file names show purpose
✅ Format ID visible in video filename
✅ Easy to inspect tmp folder contents
✅ All intermediate files preserved by default
HomeTube provides two options for managing temporary files:
By default, temporary files are preserved for resilience and caching:
# Default behavior (recommended for development/debugging)
REMOVE_TMP_FILES_AFTER_DOWNLOAD=falseThis ensures:
- ✅ Fast resume on interrupted downloads
- ✅ Instant skip when re-downloading same video
- ✅ Debugging with all intermediate files
- ✅ No wasted bandwidth re-downloading
To enable automatic cleanup after successful download:
# Enable cleanup (recommended for production/limited disk space)
REMOVE_TMP_FILES_AFTER_DOWNLOAD=trueNote: Even with cleanup enabled, files are only removed after successful completion. Failed downloads always preserve files for resume.
By default, existing tmp files are reused for intelligent caching:
# Default behavior (recommended for resilience)
NEW_DOWNLOAD_WITHOUT_TMP_FILES=falseTo force a clean slate before each download:
# Enable fresh download (useful after errors or corruption)
NEW_DOWNLOAD_WITHOUT_TMP_FILES=trueUse case: When you encounter errors or want to ensure a completely fresh download without any cached artifacts.
If disk space is a concern:
- Monitor tmp folder size:
du -sh tmp/ - Manual cleanup: Remove old video folders when done
- Selective cleanup: Keep only recent downloads in cache
- Use SSD: Fast storage improves overall performance
The tmp folder size grows with the number of processed videos, but enables instant resume and cache benefits.
# Check for cached video
existing_videos = tmp_files.find_video_tracks(tmp_subfolder_dir)
if existing_videos:
print(f"Found cached: {existing_videos[0].name}")
# Skip download# After yt-dlp downloads with video title
downloaded = tmp_subfolder_dir / f"{video_title}.mkv"
# Rename to generic name
format_id = st.session_state["downloaded_format_id"]
generic = tmp_files.get_video_track_path(tmp_subfolder_dir, format_id, "mkv")
downloaded.rename(generic)
print(f"Renamed: {downloaded.name} → {generic.name}")# When moving to destination
job_config = tmp_files.load_job_config(tmp_subfolder_dir)
intended_name = job_config["filename"]
# Move with original name (saves disk space)
final_path = dest_dir / f"{intended_name}.mkv"
shutil.move(source, final_path)- Intelligent URL Caching - How url_info.json caching works
- Unique Folder Naming - How video IDs are extracted
- File System Utils - Filesystem operations
- Temporary Files Utils - Generic naming functions
The generic file naming system is comprehensively tested:
# Run all tests
pytest tests/
# Test specific functionality
pytest tests/test_tmp_files.py
pytest tests/test_generic_file_naming.py
pytest tests/test_subtitles_utils.pyTest Coverage: 188 tests passing ✅