UNPKG

timecode-converter

Version:

Modern TypeScript library for broadcast timecode conversions with full SMPTE drop-frame support

274 lines (201 loc) 7.72 kB
# timecode-converter A modern TypeScript library for broadcast timecode conversions with full SMPTE drop-frame support. ## Features - 🎯 **Accurate Conversions** - Frame-accurate timecode to seconds conversions - 🎬 **SMPTE Drop-Frame** - Full support for 29.97 and 59.94 fps drop-frame timecode - 🤖 **Smart Auto-Detection** - Automatically handles drop-frame when appropriate - 📦 **TypeScript First** - Written in TypeScript with strict types - ✅ **Validation** - Built-in timecode validation with detailed error messages - 🚀 **Modern Build** - Dual ESM/CJS builds, tree-shakeable - 🔧 **Zero Dependencies** - No external runtime dependencies - ⚡ **High Performance** - Optimized with improved floating-point precision ## Installation ```bash npm install timecode-converter # or pnpm add timecode-converter # or yarn add timecode-converter ``` ## Quick Start ```typescript import { secondsToTimecode, timecodeToSeconds } from 'timecode-converter' // Convert seconds to timecode secondsToTimecode(90, 29.97) // '00:01:29;29' (auto drop-frame) secondsToTimecode(90, 25) // '00:01:30:00' (PAL) // Convert timecode to seconds timecodeToSeconds('00:01:30:00', 25) // 90 timecodeToSeconds('00:01:29;29', 29.97) // 90 (auto-detects drop-frame) ``` ## Drop-Frame Support This library provides comprehensive SMPTE drop-frame timecode support with smart defaults. ### What is Drop-Frame Timecode? Drop-frame is used with NTSC frame rates (29.97, 59.94 fps) to keep timecode aligned with real-world time. It works by skipping frame numbers 00 and 01 at the start of each minute, except every 10th minute. ### Smart Auto-Detection The library intelligently handles drop-frame based on context: ```typescript // Parsing: Auto-detects from format (semicolon = drop-frame) timecodeToSeconds('01:00:00;00', 29.97) // Drop-frame timecodeToSeconds('01:00:00:00', 29.97) // Non-drop // Generating: Auto-selects based on duration at 29.97/59.94 fps secondsToTimecode(3600, 29.97) // '01:00:00;00' (≥1 min = drop-frame) secondsToTimecode(30, 29.97) // '00:00:30:00' (<1 min = non-drop) // Override auto-detection secondsToTimecode(3600, 29.97, false) // '01:00:00:00' (force non-drop) secondsToTimecode(30, 29.97, true) // '00:00:29;29' (force drop-frame) ``` ## API Reference ### Core Functions #### `secondsToTimecode(seconds, frameRate, dropFrame?)` Converts seconds to timecode format. ```typescript secondsToTimecode( seconds: number, // Time in seconds frameRate: FrameRate, // 23.976, 24, 25, 29.97, 30, 50, 59.94, or 60 dropFrame?: boolean // Optional: true/false, auto-detects if omitted ): string // Returns "HH:MM:SS:FF" or "HH:MM:SS;FF" ``` #### `timecodeToSeconds(timecode, frameRate?)` Converts timecode to seconds. Auto-detects drop-frame from semicolon separator. ```typescript timecodeToSeconds( timecode: string | number, // Timecode string or seconds frameRate?: FrameRate // Required for timecode strings ): number // Returns seconds ``` #### `shortTimecode(timecode, frameRate?)` Formats timecode without frames (HH:MM:SS). ```typescript shortTimecode( timecode: string | number, frameRate?: FrameRate ): string // Returns "HH:MM:SS" ``` ### Validation Functions #### `validateTimecode(timecode, frameRate?)` Validates timecode format and values. ```typescript validateTimecode('25:00:00:00', 25) // Returns: // { // valid: false, // errors: ['Hours cannot exceed 23'], // warnings: [], // format: 'non-drop', // components: undefined // } ``` ### Helper Functions #### `isDropFrameTimecode(timecode)` Checks if timecode uses drop-frame format (semicolon separator). ```typescript isDropFrameTimecode('01:00:00;00') // true isDropFrameTimecode('01:00:00:00') // false ``` #### `isDropFrameRate(frameRate)` Checks if frame rate supports drop-frame. ```typescript isDropFrameRate(29.97) // true isDropFrameRate(25) // false ``` ## Examples ### Basic Conversions ```typescript import { secondsToTimecode, timecodeToSeconds } from 'timecode-converter' // PAL (25 fps) secondsToTimecode(90, 25) // '00:01:30:00' timecodeToSeconds('00:01:30:00', 25) // 90 // NTSC (29.97 fps) with auto drop-frame secondsToTimecode(3600, 29.97) // '01:00:00;00' (auto drop-frame) secondsToTimecode(30, 29.97) // '00:00:30:00' (auto non-drop) // Film (24 fps) secondsToTimecode(3600, 24) // '01:00:00:00' timecodeToSeconds('01:00:00:00', 24) // 3600 ``` ### Working with Drop-Frame ```typescript // Let auto-detection handle it const timecode = secondsToTimecode(durationInSeconds, 29.97) // Or be explicit const dropFrame = secondsToTimecode(3600, 29.97, true) // Force drop-frame const nonDrop = secondsToTimecode(3600, 29.97, false) // Force non-drop // Parsing handles both formats automatically timecodeToSeconds('01:00:00;00', 29.97) // Semicolon = drop-frame timecodeToSeconds('01:00:00:00', 29.97) // Colon = non-drop ``` ### Validation ```typescript import { validateTimecode } from 'timecode-converter' function processUserInput(timecode: string, fps: number) { const validation = validateTimecode(timecode, fps) if (!validation.valid) { throw new Error(validation.errors.join(', ')) } if (validation.warnings.length > 0) { console.warn('Warnings:', validation.warnings) } return timecodeToSeconds(timecode, fps) } ``` ### Round-Trip Conversions ```typescript import { timecodeToSeconds, secondsToTimecode, isDropFrameTimecode } from 'timecode-converter' function offsetTimecode(timecode: string, offsetSeconds: number, fps: number) { // Preserve drop-frame format through conversion const isDropFrame = isDropFrameTimecode(timecode) const seconds = timecodeToSeconds(timecode, fps) const newSeconds = seconds + offsetSeconds return secondsToTimecode(newSeconds, fps, isDropFrame) } ``` ## Frame Rate Reference | Frame Rate | Standard | Drop-Frame | Common Use | |------------|----------|------------|------------| | 23.976 | NTSC Film | No | Film transferred to video | | 24 | Film | No | Cinema | | 25 | PAL | No | European TV | | 29.97 | NTSC | Yes* | American TV | | 30 | NTSC | No | American TV (rare) | | 50 | PAL | No | European HD | | 59.94 | NTSC | Yes* | American HD | | 60 | NTSC | No | American HD (rare) | \* Drop-frame is optional but recommended for broadcast accuracy ## Migration from v1 If you're upgrading from the original timecode-converter, see our [Migration Guide](docs/MIGRATION.md) for detailed instructions. Key changes: - Frame rate is now required (no more defaults) - Full drop-frame timecode support - New validation functions - Improved precision and accuracy - TypeScript types included ## Development ```bash # Clone the repository git clone https://github.com/jordanburke/timecode-converter.git cd timecode-converter # Install dependencies pnpm install # Run tests pnpm test # Build the library pnpm build # Run tests in watch mode pnpm test:watch ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## Credits This is a complete TypeScript rewrite of the original [timecode-converter](https://github.com/Laurian/timecode-converter), originally extracted from [@bbc/react-transcript-editor](https://github.com/bbc/react-transcript-editor), with original domain logic from [@bevand10](https://github.com/bevand10). While this started as a fork, it has been completely rewritten with: - Full TypeScript implementation - SMPTE drop-frame support - Smart auto-detection - Comprehensive validation - Modern tooling and testing - Improved accuracy and precision ## License MIT