TickZero: AI-driven highlight extraction for CS2. Transform your Counter-Strike 2 gameplay into viral TikTok/Reels clips automatically using FREE AI.
📖 Read this in other languages: Italiano · Español · Français · Deutsch · Русский · 简体中文
- 🎮 Live Event Logging - Captures kills, headshots, and round events in real-time via CS2 Game State Integration
- ⏱️ OBS Synchronization - Precise timestamp alignment between game events and video recording
- 🤖 AI-Powered Analysis - Uses Google Gemini (FREE tier) to identify highlight-worthy moments
- ✂️ Automatic Video Editing - FFmpeg-based conversion to vertical format (9:16) with blurred background
- 🎮 Multi-GPU Support - Automatic detection and optimization for NVIDIA, AMD, and Intel GPUs
- 🔄 Continuous Recording - Record multiple matches with automatic processing between games
- ⚡ Hardware Acceleration - Smart fallback: NVIDIA NVENC → AMD AMF → Intel QSV → CPU
- Python 3.10 or higher
- OBS Studio with WebSocket plugin enabled
- FFmpeg (hardware encoding support optional)
- Counter-Strike 2
- Google API Key for Gemini (FREE tier available - no credit card required!)
Using Poetry (Recommended):
pip install poetry
poetry installDependencies: google-genai, obs-websocket-py, flask
Single command to access all features:
python -m tickzero.launcherThis opens an interactive menu where you can:
- 🎮 Start recording sessions
- 🌐 Browse match history
- ✂️ Process video files
- ⚙️ Configure settings
- ℹ️ Get help
Direct commands also available:
python -m tickzero.launcher record # Start recording
python -m tickzero.launcher process --last # Process last match
python -m tickzero.launcher --help # Show helpIf you prefer direct control:
git clone https://github.com/MACULINX/TickZero.git
cd TickZero
pip install poetry
poetry install- Open OBS Studio
- Go to Tools → WebSocket Server Settings
- Enable WebSocket server
- Note the port (default:
4455) and password (if set) - Update
configinmain.pyif needed
Copy config/gamestate_integration_highlights.cfg to your CS2 config folder:
Windows: C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\game\csgo\cfg\
Linux: ~/.steam/steam/steamapps/common/Counter-Strike Global Offensive/game/csgo/cfg/
- Visit Google AI Studio
- Sign in with your Google account
- Click "Create API Key"
- Copy your key (starts with
AIzaSy...) - Set it as environment variable:
Windows (PowerShell):
$env:GOOGLE_API_KEY = "your-api-key-here"
# Make it permanent:
[System.Environment]::SetEnvironmentVariable('GOOGLE_API_KEY', 'your-api-key-here', 'User')Linux/Mac:
export GOOGLE_API_KEY="your-api-key-here"
# Make it permanent (add to ~/.bashrc or ~/.zshrc):
echo 'export GOOGLE_API_KEY="your-api-key-here"' >> ~/.bashrc
source ~/.bashrc💡 Note: Gemini 2.5 Flash is FREE with 1500 requests/day. That's enough for ~50 matches per day!
Start the launch:
python -m tickzero.launcherFrom the menu:
- Select option [1] to start recording
- Play your CS2 match
- When done, press Ctrl+C
- Select option [2] to browse match history
- Click on a match to generate highlights
That's it! The launcher guides you through everything.
The launcher provides a two-phase pipeline:
Run this BEFORE starting your CS2 match:
python -m tickzero.launcher recordWhat happens:
- ✅ Connects to OBS WebSocket
- ✅ Starts GSI server on port 3000
- ⏳ Waits for match to start
- ✅ Automatically starts recording when the first round goes live
- ✅ Logs all game events with precise video timestamps
- ✅ Automatically stops recording when match ends (in continuous mode)
Note: With
auto_recording: True(default), recording starts automatically when the match begins, not when you run the script. This ensures you only record actual gameplay, not warmup or menu time. The system detects match start when the first round transitions to "live" phase.
Play your match normally. The system will automatically handle recording.
Manual Stop: Press Ctrl+C to stop logging (if not using continuous mode).
Events are saved to match_log.json.
Run this AFTER the match to create highlight clips:
python main.py process <path_to_recording.mp4> [api_key] [min_priority]Example:
python -m tickzero.launcher process --video "C:\Videos\cs2_match.mp4" --log "match_log.json"Parameters:
<path_to_recording.mp4>- Path to your OBS recording (via--video)<path_to_log.json>- Path to GSI log (via--log)[api_key]- Google API key (via env varGOOGLE_API_KEY)[last]- Use--lastto automatically find recent files
What happens:
- 🤖 AI analyzes
match_log.json - 🎯 Identifies highlight moments (multi-kills, clutches, headshots)
- ✂️ Creates vertical video clips in
highlights/directory
Vertical Video Specifications:
- Resolution: 1080×1920 (9:16 aspect ratio)
- Format: MP4 (H.264)
- Audio: AAC stereo (preserved from source)
- Visual Style: Center-cropped gameplay
File Naming Convention:
clip_01_3k_headshot_p9.mp4
clip_02_clutch_1v3_p8.mp4
clip_03_ace_p10.mp4
The system maintains two time references:
- System Time (
time.time()) - When events occur in real-world - Video Time - Seconds from recording start (T=0)
Conversion Formula:
Video Time = Event System Time - Recording Start Time
The GSI server monitors:
- Kills - Detected via
player.match_stats.killsincrement for the main player only - Round Changes -
round.phasetransitions (live, over, freezetime) - Context - Weapon used, headshot status, player health, round number
Note: When you die and spectate teammates, the system automatically ignores their kills. Only kills performed by the player who launched the program are logged, ensuring accurate personal highlight tracking.
The AI Director (powered by Google Gemini) prioritizes:
- 🔥 Multi-kills (2K, 3K, 4K, ACE) - More kills = Higher priority
- 💪 Clutch situations (1v2, 1v3, 1v4, 1v5) - Especially if won
- 🎯 Headshot kills - One-taps get extra points
- ⚡ High-skill plays - Quick reactions, difficult shots
- ❤️ Low health clutches - Surviving with <20 HP
Clip Duration: 8-15 seconds (optimal for TikTok/Reels)
FFmpeg applies a simple center crop:
Crop 1080x1920 from center of 16:9 source
Position: (input_width - 1080) / 2, (input_height - 1920) / 2
Result: Clean 9:16 vertical video with centered gameplay
Audio is preserved from the original recording.
Edit the config dictionary in main.py:
config = {
'obs_host': 'localhost',
'obs_port': 4455, # OBS WebSocket port
'obs_password': '', # OBS WebSocket password (if set)
'gsi_port': 3000, # GSI server port
'log_file': 'match_log.json',
'output_dir': 'highlights',
'use_gpu': True, # Enable GPU acceleration
'auto_recording': True, # Auto-start/stop recording based on match detection
'continuous_mode': True, # Auto-process after each match
'auto_process': True, # Enable automatic processing
'auto_min_priority': 6 # Minimum clip priority (1-10)
}TickZero automatically detects and uses the best available GPU encoder:
- NVIDIA NVENC (h264_nvenc) - Requires NVIDIA GPU with drivers
- AMD AMF (h264_amf) - Requires AMD Radeon GPU
- Intel QuickSync (h264_qsv) - Requires Intel CPU with integrated graphics
- CPU Fallback (libx264) - Works on any system
The system automatically tests each encoder and uses the first working option.
When continuous_mode: True, TickZero:
- Detects match end automatically (via "gameover" event)
- Processes highlights in background
- Continues recording for the next match
- No need to restart between matches!
Perfect for: Multi-match gaming sessions, competitive play, streaming
- ✅ Ensure OBS Studio is running
- ✅ Check WebSocket is enabled: Tools → WebSocket Server Settings
- ✅ Verify port and password match your config
- ✅ Verify
gamestate_integration_highlights.cfgis in the correct CS2 directory - ✅ Check GSI server is running (should show "Listening on port 3000")
- ✅ Launch CS2 and check console for GSI connection messages
- ✅ Ensure FFmpeg is installed:
ffmpeg -version - ✅ Verify source video path is correct
- ✅ Try setting
use_gpu: Falseif you encounter NVENC errors
- ✅ Check
match_log.jsoncontains kill events - ✅ Lower
min_prioritythreshold (try 4 or 5) - ✅ Verify Google API key is valid: run
python examples/test_gemini_api.py - ✅ Check you haven't exceeded daily quota (1500 requests)
- ✅ Ensure you're using the latest version of
gsi_server.pywith SteamID filtering - ✅ Check console output shows "👤 Main player locked" with your name at match start
- ✅ Run
python debug_gsi_payload.pyto verify SteamID consistency in GSI payloads
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development:
# Fork the repository
git clone https://github.com/yourusername/cs2-highlights-pipeline.git
cd cs2-highlights-pipeline
# Create a feature branch
git checkout -b feature/amazing-feature
# Make your changes and commit
git commit -m "Add amazing feature"
# Push to your fork
git push origin feature/amazing-feature
# Open a Pull RequestThis project is licensed under the MIT License - see the LICENSE file for details.
Summary: You can freely use, modify, and distribute this code, but you must include the original copyright notice and cannot hold the authors liable.
- obs-websocket-py - OBS WebSocket Python client
- Google Gemini API - AI-powered highlight analysis
- FFmpeg - Video processing engine
Parts of this project's codebase were created with the assistance of AI language models (Google Gemini, Claude) to accelerate development and improve code quality. All AI-generated code has been reviewed, tested, and adapted for this specific use case.
Special thanks to the Counter-Strike community and content creators who inspired this project.
- 🐛 Bug Reports: Open an issue
- 💡 Feature Requests: Start a discussion
- 📧 Contact: @MACULINX
Made with ❤️ by gamers, for gamers.
Star ⭐ this repo if you found it useful!