Skip to main content

viralvideo

https://github.com/user-attachments/assets/deb0e499-ac0a-4aec-bdab-f0b7923f3470

Generate TikTok-style vertical videos (9:16) that sync clips to a music template's bass pattern. When bass drops, the last frame freezes; when it lifts, the next clip plays. Ends with a 4-second SUBSCRIBE outro.

Install

pip install viralvideo

Or from source:

git clone https://github.com/maxylev/viralvideo.git
cd viralvideo
pip install -e .

External dependencies

These must be installed separately — they are not bundled with the Python package:

Tool Install Needed for
ffmpeg brew install ffmpeg or ffmpeg.org All stages
ffprobe Included with ffmpeg All stages
Node.js brew install node or nodejs.org yt-dlp YouTube signature solving
OpenRouter API key openrouter.ai --stage final only

The CLI checks for ffmpeg and ffprobe at startup and exits with install instructions if missing.

Installed automatically via pip:

Package Purpose
yt-dlp YouTube video downloading
numpy / scipy Bass detection audio analysis
requests OpenRouter API calls

Quick start

# Create a URL file (see URL format below)
cat > urls.txt << 'EOF'
https://www.youtube.com/watch?v=VIDEO_ID?start=00:01:16&crop=left:15
https://www.youtube.com/watch?v=VIDEO_ID?start=00:00:30
EOF

# Test run — preview timing and cropping, no API calls
viralvideo upscale -i urls.txt -s test

# Final run — enhance freeze frames, produce final video
viralvideo upscale -i urls.txt -s final

Command reference

viralvideo upscale [OPTIONS]

Required:

Option Flag Description
--input -i Text file with YouTube URLs (one per line)
--stage -s test, final, or final:RANGE

Optional:

Option Flag Default Description
--audio -a bass_pulse Audio template: built-in name or path to .wav/.mp4
--resolution -r 1080x1920 Output resolution in WxH format
--output -o output/ next to input file Output directory
--outro-text SUBSCRIBE Text shown on the outro screen (seconds 20–24)
--model -m google/gemini-3.1-flash-image-preview OpenRouter model for frame enhancement
--api-key $OPENROUTER_API_KEY OpenRouter API key (or set env var)

Stage values

Value Behavior
test Build video with raw freeze frames — no API calls
final Enhance all freeze frames via OpenRouter
final:1 Enhance only video 1, reuse cached frames for the rest
final:2-4 Enhance videos 2, 3, 4; reuse cached for 1 and 5
final:1,3-5 Enhance videos 1, 3, 4, 5

Specifying a video number in the range always calls the API, overwriting any cached enhanced frame. Videos not in the range reuse a cached enhanced_*.png if it exists.

Resolution examples

viralvideo upscale -i urls.txt -s test -r 1080x1920   # TikTok 1080p
viralvideo upscale -i urls.txt -s test -r 720x1280    # 720p
viralvideo upscale -i urls.txt -s test -r 540x960     # 540p (fast preview)

Audio templates

The --audio flag accepts a built-in name or a file path:

# Built-in (ships with the package)
viralvideo upscale -i urls.txt -s test -a bass_pulse

# Custom audio
viralvideo upscale -i urls.txt -s test -a /path/to/my_template.wav
viralvideo upscale -i urls.txt -s test -a /path/to/my_template.mp4
Name Description
bass_pulse 5-bass-note pattern at ~2s intervals, 24s total

Model selection

# Default model
viralvideo upscale -i urls.txt -s final -m google/gemini-3.1-flash-image-preview

# Alternative model
viralvideo upscale -i urls.txt -s final -m google/gemini-2.5-flash

Outro text

The last 4 seconds show a black screen with centered text. Customize or disable:

viralvideo upscale -i urls.txt -s test --outro-text "FOLLOW FOR MORE"
viralvideo upscale -i urls.txt -s test --outro-text ""             # black screen, no text

Output directory

By default, outputs go to output/ next to the input file. Redirect with --output:

viralvideo upscale -i urls.txt -s test -o /tmp/my_video

URL file format

One URL per line. Each URL supports start and crop parameters:

https://www.youtube.com/watch?v=VIDEO_ID?start=HH:MM:SS&crop=SIDE[:PCT]
Parameter Required Description
start yes Playback start offset (HH:MM:SS, MM:SS, or seconds)
crop no Crop alignment: left, right, center, top, bottom
crop pct no Percentage shift from center. 0 = center, 100 = fully to that edge. Bare crop=left defaults to 100%.

Examples

# Center crop (default)
https://www.youtube.com/watch?v=abc123?start=00:01:16

# Full left crop
https://www.youtube.com/watch?v=abc123?start=00:01:16&crop=left

# 15% shift left from center
https://www.youtube.com/watch?v=abc123?start=00:01:16&crop=left:15

# Full bottom crop
https://www.youtube.com/watch?v=abc123?start=00:00:30&crop=bottom

# 30% shift down from center
https://www.youtube.com/watch?v/abc123?start=00:00:30&crop=bottom:30

5 URLs = 5 videos, one per bass note detected in the template.

How it works

Template audio
──────────────╥────────────────────╥──────────────────╥─── ...
              ║ BASS               ║ BASS              ║
              ║                    ║                    ║
Video         ║                    ║                    ║
── vid 1 ────║── freeze ──────────║── vid 2 ──────────║── freeze ── ...
              ║ (last frame vid 1) ║                    ║ (last frame vid 2)
  1. Analyze the template audio for bass notes using hysteresis threshold on low-frequency RMS
  2. Download each YouTube URL at its start offset via yt-dlp
  3. Crop each video to 9:16 using the crop parameter for vertical framing
  4. Segment: play during vocals/silence, freeze on the last frame during bass, outro with customizable text for seconds 20–24
  5. Enhance freeze frames via OpenRouter API (final stage only)
  6. Assemble all segments at 30fps at the target resolution, mux with audio, trim to 24 seconds

Crop behavior

All videos are cropped to 9:16. The crop parameter controls framing:

  • Landscape (wider than 9:16): left/right shift horizontal crop
  • Portrait (narrower than 9:16): top/bottom shift vertical crop
  • Percentage: crop=left:0 = center, crop=left:50 = halfway, crop=left:100 = fully left

Changing the crop parameter changes the cached filename, so re-running with a different crop will re-crop automatically.

Output files

Outputs go to an output/ directory next to the input file by default, or wherever --output points:

output/
├── test/                    # --stage test
│   ├── source_*.mp4             Downloaded videos
│   ├── cropped_*.mp4            9:16 cropped videos
│   ├── seg_*.mp4                Individual segments
│   ├── play_last_*.png          Extracted last frames
│   └── test_video.mp4          Final test video
└── final/                   # --stage final
    ├── (same as test/)
    ├── enhanced_*.png            AI-upscaled freeze frames
    └── final_video.mp4          Final enhanced video

Cookies for yt-dlp

If downloads fail due to authentication, place a cookies.txt (Netscape format) next to your input file. It will be picked up automatically.

Development

pip install -e ".[dev]"
pytest

Project structure

src/viralvideo/
├── __init__.py          Version + built-in audio registry
├── cli.py               CLI entry point + dependency checks
├── upscale.py           Upscale video type (play/freeze/bass)
├── audio.py             Bass detection & segment analysis
├── downloader.py        YouTube download & URL parsing
├── enhance.py           OpenRouter frame enhancement
├── ffmpeg_tools.py      ffmpeg/ffprobe wrappers & crop logic
└── assets/audio/
    └── bass_pulse.wav   Built-in audio template

License

MIT

Metadata

Release files for viralvideo 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for viralvideo 0.1.0
File Size Uploaded Provenance Actions
viralvideo-0.1.0.tar.gz 2.0 MB With provenance Details for viralvideo-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for viralvideo 0.1.0
File Interpreter ABI Platform Actions
viralvideo-0.1.0-py3-none-any.whl Python 3 none any Details for viralvideo-0.1.0-py3-none-any.whl

Total release size: 4.0 MB

Release files / viralvideo-0.1.0.tar.gz

Download URL viralvideo-0.1.0.tar.gz
Size 2.0 MB
Tags Source
SHA-256 checksum
How to use checksums
79bc9600f859ca68240b972c6a46b4ac2519b71251d7940c026f460636b3ef69
BLAKE2b-256 checksum
How to use checksums
ed9525e7ae42f986ccf4e71cdf4b57bc9cc98289f87ee292c545a18d5f7ae784
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 18, 2026.

Transparency log

Release files / viralvideo-0.1.0-py3-none-any.whl

Download URL viralvideo-0.1.0-py3-none-any.whl
Size 2.0 MB
Tags Python 3
SHA-256 checksum
How to use checksums
e2a4be1ce2d912e8746006098bef4809fa1f93dc13e2f3bc2be9fa8bc4674c84
BLAKE2b-256 checksum
How to use checksums
69f3c91fc1acd9d3b93d5a275284b7420af9803f2688843f8e16792242c27235
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 18, 2026.

Transparency log

Security for viralvideo 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for viralvideo-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 18, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page