Skip to content

Latest commit

 

History

History
313 lines (255 loc) · 8.98 KB

File metadata and controls

313 lines (255 loc) · 8.98 KB

Contributing to Subtide

Thank you for your interest in contributing to Subtide!

Table of Contents


Development Setup

Backend

  1. Navigate to backend directory:

    cd backend
  2. Create virtual environment:

    python -m venv venv
    source venv/bin/activate  # Windows: venv\Scripts\activate
  3. Install dependencies:

    pip install -r requirements.txt
  4. Configure environment (optional):

    cp .env.example .env
    # Edit .env with your settings
  5. Run the server:

    # Development mode with hot reload
    export FLASK_ENV=development
    python app.py
    
    # OR use the run script
    ./run.sh

Extension

  1. Open Chrome and navigate to chrome://extensions
  2. Enable Developer mode (top right toggle)
  3. Click Load unpacked
  4. Select the extension folder
  5. The extension will appear in your toolbar

Hot Reload:

  • Make changes to JS/HTML/CSS files
  • Click the refresh icon on the extension card in chrome://extensions
  • Or use a tool like Extension Reloader

Project Structure

subtide/
├── backend/                        # Python Flask server
│   ├── app.py                      # Flask entry point
│   ├── config.py                   # Configuration management
│   ├── routes/
│   │   └── translation.py          # API endpoint handlers
│   ├── services/
│   │   ├── whisper_service.py      # Speech-to-text (MLX/faster-whisper)
│   │   ├── translation_service.py  # LLM translation logic
│   │   ├── youtube_service.py      # YouTube data extraction
│   │   └── process_service.py      # Pipeline orchestration
│   ├── utils/
│   │   ├── model_utils.py          # Model loading/management
│   │   ├── partial_cache.py        # Translation caching
│   │   ├── language_detection.py   # Language utilities
│   │   ├── logging_utils.py        # Structured logging, request IDs
│   │   ├── retry.py                # Retry decorator with backoff
│   │   └── hallucination_filter.py # Whisper output filtering
│   ├── tests/                      # Unit tests
│   ├── requirements.txt            # Python dependencies
│   ├── Dockerfile                  # Container configuration
│   └── docker-compose.yml          # Multi-tier deployment
│
├── extension/                      # Chrome Extension (Manifest V3)
│   ├── manifest.json               # Extension manifest
│   ├── _locales/                   # Internationalization
│   │   └── en/messages.json        # English strings
│   ├── icons/                      # Extension icons (16, 48, 128px)
│   └── src/
│       ├── background/
│       │   └── service-worker.js   # Background service worker
│       ├── content/
│       │   ├── youtube.js          # Main YouTube content script
│       │   ├── youtube-shorts.js   # Shorts pre-translation
│       │   ├── youtube-subtitles.js # Subtitle sync/rendering
│       │   ├── youtube-ui.js       # Player UI controls
│       │   ├── youtube-styles.js   # CSS injection
│       │   ├── youtube-constants.js # Shared constants
│       │   ├── youtube-status.js   # Status management
│       │   ├── youtube-export.js   # Subtitle export (SRT/VTT)
│       │   ├── twitch.js           # Twitch integration
│       │   ├── generic.js          # Generic video support
│       │   └── shorts-interceptor.js # Page-context interceptor
│       ├── lib/
│       │   └── debug.js            # Debug logging utility
│       ├── offscreen/              # Offscreen document for audio
│       └── popup/
│           ├── popup.html          # Extension popup UI
│           └── popup.js            # Popup logic
│
├── scripts/                        # Build/utility scripts
├── docs/                           # Additional documentation
├── SPECIFICATION.md                # Technical specification
├── ISSUES.md                       # Known issues
├── CLAUDE.md                       # AI assistant guidelines
└── LICENSE                         # MIT License

Testing

We use pytest for backend testing. Current test count: 262+ tests.

Run All Tests

cd backend
PYTHONPATH=$PYTHONPATH:$(pwd)/.. python -m pytest tests/ -v

Run with Coverage

PYTHONPATH=$PYTHONPATH:$(pwd)/.. python -m pytest tests/ --cov=. --cov-report=term-missing --cov-fail-under=50

Run Specific Test Categories

# Unit tests only (fast, no network)
python -m pytest tests/ -m "not slow" -v

# Real video integration tests (requires network)
python -m pytest tests/test_real_video_pipeline.py -v -s

# Cache layer tests
python -m pytest tests/test_cache_service.py tests/test_partial_cache.py -v

# LLM provider tests
python -m pytest tests/test_llm_factory.py -v

Test Markers

  • @pytest.mark.slow - Tests that require network access or take >10s
  • @pytest.mark.network - Tests that require internet connectivity

Test Utilities

The utils/retry.py module provides a retry decorator for flaky tests:

from backend.utils.retry import retry

@retry(max_attempts=3, delay=1.0, exceptions=(TimeoutError,))
def test_flaky_network_call():
    ...

CI Integration

Every push to GitHub triggers:

  1. code-quality - flake8, black, isort checks
  2. security-scan - Bandit security analysis, pip-audit
  3. test-backend - Full pytest suite with 50% coverage requirement

PRs will fail if any job fails.


Code Style

Python (Backend)

  • Follow PEP 8 style guide
  • Use type hints where possible
  • Maximum line length: 100 characters
  • Use docstrings for public functions
def translate_text(text: str, target_lang: str) -> str:
    """
    Translate text to the target language.

    Args:
        text: The source text to translate
        target_lang: ISO 639-1 language code

    Returns:
        Translated text string
    """
    ...

JavaScript (Extension)

  • Use modern ES6+ syntax
  • Use const by default, let when needed
  • Avoid var
  • Use template literals for string interpolation
  • Clean, readable code with meaningful variable names
// Good
const translateVideo = async (videoId, targetLang) => {
    const response = await chrome.runtime.sendMessage({
        action: 'translate',
        videoId,
        targetLang
    });
    return response.subtitles;
};

// Avoid
var translateVideo = function(id, lang) {
    return new Promise(function(resolve) {
        chrome.runtime.sendMessage({action: 'translate', videoId: id, targetLang: lang}, function(r) {
            resolve(r.subtitles);
        });
    });
};

Commits

  • Use clear, descriptive commit messages
  • Start with a verb: "Add", "Fix", "Update", "Remove"
  • Reference issues when applicable: "Fix #123"
Good: "Add YouTube Shorts pre-translation support"
Good: "Fix memory leak in subtitle observer"
Bad:  "stuff"
Bad:  "WIP"

Pull Requests

  1. Fork the repository
  2. Create a feature branch:
    git checkout -b feature/amazing-feature
  3. Make your changes with clear commits
  4. Run tests to ensure nothing is broken
  5. Push to your fork:
    git push origin feature/amazing-feature
  6. Open a Pull Request with:
    • Clear title describing the change
    • Description of what/why/how
    • Screenshots for UI changes
    • Link to related issues

PR Checklist

  • Tests pass locally
  • Code follows style guidelines
  • No console.log statements (use vtLog for debugging)
  • No hardcoded secrets or API keys
  • Documentation updated if needed

Debug Logging

The extension includes a debug logging utility (src/lib/debug.js).

Usage in Content Scripts

// Available globally as vtLog
vtLog.debug('Detailed debug info', { data });
vtLog.info('General info');
vtLog.warn('Warning message');
vtLog.error('Error occurred', error);

Log Levels

  • debug — Verbose debugging (disabled in production)
  • info — General information
  • warn — Warnings
  • error — Errors

Viewing Logs

  1. Open Chrome DevTools (F12)
  2. Go to Console tab
  3. Filter by [VideoTranslate] prefix

Issues

Please check ISSUES.md for known bugs and limitations before opening a new issue.

When reporting bugs, include:

  • Browser version
  • Extension version
  • Steps to reproduce
  • Expected vs actual behavior
  • Console logs if applicable