{"id":31286951,"url":"https://github.com/kperreau/wordsubgen","last_synced_at":"2026-01-24T17:16:06.752Z","repository":{"id":315834536,"uuid":"1058806544","full_name":"kperreau/wordsubgen","owner":"kperreau","description":"A Go library and CLI tool for generating ASS (Advanced SubStation Alpha) subtitle files with word-by-word fade-in effects. Perfect for creating dynamic subtitles where words appear sequentially with smooth fade transitions.","archived":false,"fork":false,"pushed_at":"2026-01-22T19:20:44.000Z","size":6303,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-23T12:22:33.519Z","etag":null,"topics":["advanced-substation-alpha","ass","cli","fade-in","go","golang","karaoke","ssa","subtitles","text-animation","word-by-word"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kperreau.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-17T15:15:39.000Z","updated_at":"2026-01-22T19:20:07.000Z","dependencies_parsed_at":"2025-09-21T03:57:18.861Z","dependency_job_id":"32d87847-1245-4abf-9d5d-f206057b11d4","html_url":"https://github.com/kperreau/wordsubgen","commit_stats":null,"previous_names":["kperreau/wordsubgen"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/kperreau/wordsubgen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kperreau%2Fwordsubgen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kperreau%2Fwordsubgen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kperreau%2Fwordsubgen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kperreau%2Fwordsubgen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kperreau","download_url":"https://codeload.github.com/kperreau/wordsubgen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kperreau%2Fwordsubgen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28732310,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T10:24:43.181Z","status":"ssl_error","status_checked_at":"2026-01-24T10:24:36.112Z","response_time":89,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["advanced-substation-alpha","ass","cli","fade-in","go","golang","karaoke","ssa","subtitles","text-animation","word-by-word"],"created_at":"2025-09-24T10:58:52.086Z","updated_at":"2026-01-24T17:16:06.744Z","avatar_url":"https://github.com/kperreau.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wordsubgen\n\nA Go library and CLI tool for generating ASS (Advanced SubStation Alpha) subtitle files with word-by-word fade-in effects. Perfect for creating dynamic subtitles where words appear sequentially with smooth fade transitions.\n\n## Features\n\n- **Word-by-word fade effects**: Each word fades in sequentially using ASS `\\alpha` tags\n- **Structured JSON input**: Generate from timed words (`word`, `start`, `end` in seconds) with `--json` / `--json-file`; `StartDelay` shifts all timings (e.g. 1500 ms = 1.5 s offset)\n- **Karaoke support**: Optional karaoke mode with `\\k` tags for word highlighting\n- **Shadow effects**: Customizable shadow with directional control using `\\xshad` and `\\yshad` tags\n- **Flexible configuration**: Customizable fonts, colors, timing, alignment, and styling\n- **Library API**: Use as a Go library in your own projects\n- **CLI tool**: Easy-to-use command-line interface with structured logging\n\n## Demo\n\nHere's a visual example of the word-by-word fade effect generated by wordsubgen:\n\n![Word-by-word fade effect demo](assets/example.gif)\n\nThis demo was generated using the following command:\n\n```bash\nwordsubgen --lines \"This is a super test|Hello world \\!\"  --font \"Outfit\" --fontsize 85 --shadow-enabled --shadow-x 3 --shadow-y 8 --width 1080 --height 734 --out subtitle.ass\n```\n\n## Installation\n\n### CLI Tool Installation\n\nTo install the command-line tool:\n\n```bash\ngo install github.com/kperreau/wordsubgen/cmd/wordsubgen@latest\n```\n\n### Package Installation (for Go projects)\n\nTo use wordsubgen as a library in your Go project:\n\n```bash\ngo get github.com/kperreau/wordsubgen@latest\n```\n\nThen import it in your Go code:\n```go\nimport \"github.com/kperreau/wordsubgen\"\n```\n\n### Development Installation\n\nFor development work on the wordsubgen project itself:\n\n```bash\ngit clone https://github.com/kperreau/wordsubgen.git\ncd wordsubgen\nmake deps\nmake build\n```\n\nOr install the CLI to your GOPATH/bin:\n```bash\nmake install  # Installs to GOPATH/bin\n```\n\n### Requirements\n\n- **Go 1.25.0+**: Required for building from source\n- **Make**: Required for using the Makefile (optional, you can use `go build` directly)\n\n## Quick Start\n\n### CLI Usage\n\nGenerate subtitles from command line:\n\n```bash\n# Basic usage\nwordsubgen --lines \"Hello world|This is a test\" --out subtitle.ass\n\n# Custom styling\nwordsubgen --lines \"Hello world\" --color \"#FF0000\" --fontsize 72 --delay 500\n\n# Karaoke mode\nwordsubgen --lines \"Hello world\" --karaoke --delay 400\n\n# From file\nwordsubgen --file input.txt --out subtitle.ass\n\n# From structured JSON (words with start/end in seconds); --start-delay 1500 = 1.5 s shift\nwordsubgen --json-file words.json --start-delay 1500 --out subtitle.ass\n\n# Show help with current default values\nwordsubgen --help\n```\n\n### Library Usage\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"github.com/kperreau/wordsubgen\"\n)\n\nfunc main() {\n    // Create configuration\n    cfg := wordsubgen.DefaultConfig()\n    cfg.FontSize = 48\n    cfg.PrimaryColor = wordsubgen.ColorToASS(\"#FF0000\")\n    cfg.PerWordDelay = 500\n\n    // Enable shadow with diagonal direction (more downward than sideways)\n    cfg.ShadowEnabled = true\n    cfg.ShadowX = 3  // Horizontal offset\n    cfg.ShadowY = 8  // Vertical offset (more downward)\n\n    // Generate ASS content\n    lines := []string{\"Hello world\", \"This is a test\"}\n    content, err := wordsubgen.GenerateASS(cfg, lines)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Write to file\n    err = wordsubgen.WriteASS(\"output.ass\", content, cfg.Logger)\n    if err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n## Structured JSON Input\n\nYou can generate subtitles from a JSON structure with a `segments` array. Each segment is a phrase with a `words` array; each word has `word`, `start` and `end` (in **seconds**). Extra fields anywhere are ignored.\n\n```json\n{\n  \"segments\": [\n    {\n      \"words\": [\n        {\"word\": \"Découvrez\", \"start\": 0.162, \"end\": 1.024},\n        {\"word\": \"cette\", \"start\": 1.064, \"end\": 1.344},\n        {\"word\": \"superbe\", \"start\": 1.404, \"end\": 1.845}\n      ]\n    },\n    {\n      \"words\": [\n        {\"word\": \"Deuxième\", \"start\": 2.0, \"end\": 2.5},\n        {\"word\": \"phrase\", \"start\": 2.6, \"end\": 3.0}\n      ]\n    }\n  ]\n}\n```\n\n- **StartDelay** (e.g. `--start-delay 1500`): adds 1.5 seconds to every `start` and `end` so subtitles start 1.5 s later in the video.\n- **PerWordDelay** is ignored (timings come from the JSON).\n- **FadeDuration** is still used for the word fade-in effect.\n\n### CLI\n\n```bash\nwordsubgen --json-file words.json --start-delay 1500 --out subtitle.ass\nwordsubgen --json '{\"segments\":[{\"words\":[{\"word\":\"Hello\",\"start\":0,\"end\":0.5},{\"word\":\"world\",\"start\":0.6,\"end\":1.2}]}]}' --out subtitle.ass\n```\n\n### Library\n\n```go\ndata, _ := os.ReadFile(\"words.json\")\nphrases, err := wordsubgen.ParseStructuredJSON(data)\nif err != nil {\n    log.Fatal(err)\n}\ncfg := wordsubgen.DefaultConfig()\ncfg.StartDelay = 1500 // 1.5 s shift\ncontent, err := wordsubgen.GenerateASSFromStructured(cfg, phrases)\n// then wordsubgen.WriteASS(...)\n```\n\n## Flexible Logging Interface\n\nwordsubgen features a flexible logging interface that allows you to inject your own logger implementation. The library comes with several built-in loggers and supports popular logging libraries like zerolog (recommended), logrus, and others.\n\n### Built-in Loggers\n\n```go\n// Default logger (uses Go's standard log package)\ncfg.Logger = wordsubgen.NewDefaultLogger()\n\n// No-operation logger (silent, useful for tests)\ncfg.Logger = wordsubgen.NewNoOpLogger()\n```\n\n### Custom Logger Implementation\n\n```go\ntype MyCustomLogger struct{}\n\nfunc (l *MyCustomLogger) Debug(msg string, fields ...wordsubgen.Field) {\n    // Your debug implementation\n}\n\nfunc (l *MyCustomLogger) Info(msg string, fields ...wordsubgen.Field) {\n    // Your info implementation\n}\n\nfunc (l *MyCustomLogger) Error(msg string, fields ...wordsubgen.Field) {\n    // Your error implementation\n}\n\nfunc (l *MyCustomLogger) Warn(msg string, fields ...wordsubgen.Field) {\n    // Your warning implementation\n}\n\n// Use your custom logger\ncfg.Logger = \u0026MyCustomLogger{}\n```\n\n### Logging Features\n\n- **Structured logging**: Support for key-value fields\n- **Multiple log levels**: Debug, Info, Error, Warn\n- **Zero dependencies**: No forced logging library dependencies\n- **Flexible**: Easy to integrate with any logging system\n- **zerolog support**: Recommended for high-performance structured logging\n\n## Configuration Reference\n\n### Video Settings\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `Width` | int | 1080 | Video width in pixels |\n| `Height` | int | 1920 | Video height in pixels |\n\n### Font Settings\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `FontName` | string | \"Arial\" | Font family name |\n| `FontSize` | int | 64 | Font size in points |\n\n### Colors (ASS format: \u0026H00BBGGRR)\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `PrimaryColor` | string | \"\u0026H00FFFFFF\" | Text color (white) |\n| `SecondaryColor` | string | \"\u0026H0000FFFF\" | Karaoke highlight color (yellow) |\n| `OutlineColor` | string | \"\u0026H00000000\" | Outline color (black) |\n| `BackColor` | string | \"\u0026H64000000\" | Background color (semi-transparent) |\n\n\u003e **Color Conversion**: Use `ColorToASS()` to convert hex colors (#RRGGBB) to ASS format, and `ColorToHex()` to convert ASS colors back to hex format.\n\n### Style Settings\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `Bold` | bool | true | Bold text |\n| `Italic` | bool | false | Italic text |\n| `Underline` | bool | false | Underlined text |\n| `StrikeOut` | bool | false | Strikethrough text |\n\n### Scaling and Spacing\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `ScaleX` | int | 100 | Horizontal scale (%) |\n| `ScaleY` | int | 100 | Vertical scale (%) |\n| `Spacing` | int | 0 | Character spacing |\n| `Angle` | int | 0 | Text rotation angle |\n\n### Border and Shadow\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `BorderStyle` | int | 1 | Border style (1=outline, 3=box) |\n| `Outline` | int | 4 | Outline width |\n| `Shadow` | int | 0 | Shadow width |\n\n### Shadow Effects\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `ShadowEnabled` | bool | false | Enable/disable shadow effect |\n| `ShadowX` | int | 3 | Horizontal shadow offset (-50 to 50) |\n| `ShadowY` | int | 8 | Vertical shadow offset (-50 to 50) |\n\n\u003e **Shadow Direction**: Positive values move the shadow right (X) and down (Y). Negative values move left and up. The default values (X=3, Y=8) create a diagonal shadow that's more downward than sideways.\n\n### Alignment\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `Alignment` | int | 2 | Text alignment (1=bottom-left, 2=bottom-center, 3=bottom-right, etc.) |\n\n### Margins\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `MarginL` | int | 40 | Left margin |\n| `MarginR` | int | 40 | Right margin |\n| `MarginV` | int | 120 | Vertical margin |\n\n### Timing Settings\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `StartDelay` | int | 0 | Delay before starting subtitles (milliseconds). In structured JSON mode: added to all word start/end times (e.g. 1500 = 1.5 s shift). |\n| `PerWordDelay` | int | 300 | Delay between words (milliseconds). **Ignored** when using structured JSON (`GenerateASSFromStructured`). |\n| `FadeDuration` | int | 140 | Fade duration (milliseconds) |\n| `LineHold` | int | 2000 | Line hold duration (milliseconds). Not applied in structured JSON mode. |\n| `LineGap` | int | 0 | Gap between lines (milliseconds). Not applied in structured JSON mode. |\n\n### Features\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `Karaoke` | bool | false | Enable karaoke mode |\n\n### Encoding\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `Encoding` | int | 1 | Text encoding (1=ANSI, 0=Unicode) |\n\n## CLI Reference\n\n\u003e **Note**: All default values are dynamically generated from the `DefaultConfig()` function. Use `--help` to see the current default values.\n\n### Input Options (mutually exclusive)\n\n- `--lines string`: Input lines separated by `|` (e.g., 'Hello world|Second line')\n- `--file string`: Input file with lines (one per line)\n- `--json string`: Structured JSON: `{\"segments\":[{\"words\":[{\"word\":\"...\",\"start\":0.1,\"end\":0.5},...]},...]}`. `start`/`end` in seconds. Extra fields ignored.\n- `--json-file string`: Path to a structured JSON file (same format as `--json`).\n\nWith `--json` or `--json-file`: `--delay` (PerWordDelay) is ignored; `--start-delay` shifts all word timings (e.g. `--start-delay 1500` adds 1.5 s to every start/end).\n\n### Output Options\n\n- `--out string`: Output ASS file path (default: output.ass)\n\n### Video Settings\n\n- `--width int`: Video width (default: 1080)\n- `--height int`: Video height (default: 1920)\n\n### Font Settings\n\n- `--font string`: Font name (default: Arial)\n- `--fontsize int`: Font size (default: 64)\n\n### Colors (hex format)\n\n- `--color string`: Primary text color (default: #FFFFFF)\n- `--secondary string`: Secondary color for karaoke (default: #FFFF00)\n- `--outline string`: Outline color (default: #000000)\n- `--background string`: Background color in ASS format (default: #64000000)\n\n### Style Settings\n\n- `--bold`: Bold text (default: true)\n- `--italic`: Italic text (default: false)\n- `--underline`: Underline text (default: false)\n- `--strikeout`: Strikeout text (default: false)\n\n### Scaling\n\n- `--scalex int`: Horizontal scale % (default: 100)\n- `--scaley int`: Vertical scale % (default: 100)\n- `--spacing int`: Character spacing (default: 0)\n- `--angle int`: Text angle (default: 0)\n\n### Border and Shadow\n\n- `--borderstyle int`: Border style (default: 1)\n- `--outlinewidth int`: Outline width (default: 4)\n- `--shadow int`: Shadow width (default: 0)\n\n### Shadow Effects\n\n- `--shadow-enabled`: Enable shadow effect (default: false)\n- `--shadow-x int`: Horizontal shadow offset (default: 3)\n- `--shadow-y int`: Vertical shadow offset (default: 8)\n\n### Alignment\n\n- `--alignment int`: Text alignment (1=bottom-left, 2=bottom-center, 3=bottom-right, etc.) (default: 2)\n\n### Margins\n\n- `--marginl int`: Left margin (default: 40)\n- `--marginr int`: Right margin (default: 40)\n- `--marginv int`: Vertical margin (default: 120)\n\n### Timing\n\n- `--start-delay int`: Delay before starting subtitles in ms (default: 0)\n- `--delay int`: Delay between words in ms (default: 300)\n- `--fade int`: Fade duration in ms (default: 140)\n- `--hold int`: Line hold duration in ms (default: 2000)\n- `--gap int`: Gap between lines in ms (default: 0)\n\n### Features\n\n- `--karaoke`: Enable karaoke mode (default: false)\n\n### Other\n\n- `--help`: Show help with current default values\n\n## Examples\n\n### Basic Example\n\n```bash\nwordsubgen --lines \"Hello world|This is a test\" --out subtitle.ass\n```\n\n### Custom Styling\n\n```bash\nwordsubgen --lines \"Hello world\" --fontsize 48 --color \"#FF0000\" --bold\n```\n\n### Karaoke Mode\n\n```bash\nwordsubgen --lines \"Hello world\" --karaoke --delay 500\n```\n\n### From File\n\n```bash\necho -e \"First line\\nSecond line\\nThird line\" \u003e input.txt\nwordsubgen --file input.txt --out subtitle.ass\n```\n\n### Shadow Effects\n\n```bash\n# Diagonal shadow (more downward than sideways)\nwordsubgen --lines \"Hello world\" --shadow-enabled --shadow-x 3 --shadow-y 8\n\n# Horizontal shadow (more sideways)\nwordsubgen --lines \"Hello world\" --shadow-enabled --shadow-x 8 --shadow-y 3\n\n# No shadow (explicitly disabled)\nwordsubgen --lines \"Hello world\" --shadow-enabled=false\n```\n\n### Start Delay\n\n```bash\n# Delay subtitles by 100ms\nwordsubgen --lines \"Hello world\" --start-delay 100\n\n# Delay subtitles by 1 second\nwordsubgen --lines \"Hello world\" --start-delay 1000\n\n# Delay subtitles by 2.5 seconds\nwordsubgen --lines \"Hello world\" --start-delay 2500\n```\n\n### Structured JSON\n\n```bash\n# From file with 1.5 s global delay\nwordsubgen --json-file words.json --start-delay 1500 --out subtitle.ass\n\n# Inline JSON (one phrase)\nwordsubgen --json '{\"segments\":[{\"words\":[{\"word\":\"Hello\",\"start\":0,\"end\":0.5},{\"word\":\"world\",\"start\":0.6,\"end\":1.2}]}]}' --out subtitle.ass\n```\n\n### Quick Demo with Makefile\n\n```bash\n# Generate sample files\nmake run-cli         # Basic sample\nmake run-cli-custom  # Custom styling\nmake run-cli-karaoke # Karaoke mode\n```\n\n## Development\n\n### Project Structure\n\n```\nwordsubgen/\n├── cmd/wordsubgen/\n│   ├── main.go                    # CLI application entry point\n│   └── wordsubgen                 # Built binary (after make build)\n├── assets/                        # Assets\n│   └── example.gif                # Demo animation\n├── config.go                      # Configuration and validation\n├── config_test.go                 # Configuration tests\n├── generator.go                   # ASS generation logic\n├── generator_test.go              # Generator tests\n├── integration_test.go            # Integration tests\n├── logger.go                      # Flexible logging interface\n├── logger_test.go                 # Logger tests\n├── writer.go                      # File I/O operations\n├── writer_test.go                 # Writer tests\n├── go.mod                         # Go module definition\n├── go.sum                         # Go module checksums\n├── Makefile                       # Build automation\n├── README.md                      # Documentation\n├── LICENSE                        # MIT License\n├── input.txt                      # Sample input file\n├── subs.exemple.ass               # Example subtitle file\n└── subtitle.ass                   # Generated subtitle file\n```\n\n### Building\n\n```bash\nmake build          # Build CLI binary\nmake install        # Install CLI to GOPATH/bin\nmake clean          # Clean build artifacts\n```\n\n### Testing\n\n```bash\nmake test           # Run all tests\nmake test-coverage  # Run tests with coverage report\nmake check          # Run fmt, lint, and test\n```\n\n### Running Examples\n\n```bash\nmake run-cli         # Run CLI with sample input\nmake run-cli-custom  # Run CLI with custom styling\nmake run-cli-karaoke # Run CLI with karaoke mode\n```\n\n### Code Quality\n\n```bash\nmake fmt            # Format code\nmake lint           # Lint code\nmake deps           # Install dependencies\n```\n\n### Development Workflow\n\n```bash\nmake dev            # Complete dev workflow: deps, fmt, lint, test, build\nmake release        # Build release binaries for multiple platforms\n```\n\n### Available Make Targets\n\n```bash\nmake help           # Show all available targets\n```\n\n### Testing\n\nThe project includes test coverage:\n\n- **Unit tests**: Individual component testing (`*_test.go` files)\n\nRun tests with:\n```bash\nmake test           # Run all tests\nmake test-coverage  # Generate coverage report\nmake ci-test        # Run all tests for ci\n```\n\n## Usage Examples\n\n### Basic Library Usage with Custom Logger\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"github.com/kperreau/wordsubgen\"\n)\n\nfunc main() {\n    // Create configuration with custom logger\n    cfg := wordsubgen.DefaultConfig()\n    cfg.Logger = wordsubgen.NewDefaultLogger() // or your custom logger\n    \n    // Generate subtitles\n    lines := []string{\"Hello world\", \"This is a test\"}\n    content, err := wordsubgen.GenerateASS(cfg, lines)\n    if err != nil {\n        log.Fatal(err)\n    }\n    \n    // Write to file\n    err = wordsubgen.WriteASS(\"output.ass\", content, cfg.Logger)\n    if err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n### CLI with Help\n\n```bash\n# Show help with current default values\nwordsubgen --help\n```\n\nThis will display all available options with their current default values, which are dynamically generated from the `DefaultConfig()` function.\n\n## ASS Format Details\n\nThe generated ASS files follow the Advanced SubStation Alpha v4.00+ format with:\n\n- **Script Info**: Basic metadata and video resolution\n- **V4+ Styles**: Font, color, and styling definitions\n- **Events**: Dialogue lines with timing and effects\n\n### Word Fade Effect\n\nEach word uses the `\\alpha` tag for fade effects:\n\n```\n{\\alpha\u0026HFF\u0026\\t(start,end,\\alpha\u0026H00\u0026)}word\n```\n\nWhere:\n- `\\alpha\u0026HFF\u0026`: Start invisible (fully transparent)\n- `\\t(start,end,\\alpha\u0026H00\u0026)`: Transition to visible over time\n- `start,end`: Timing in milliseconds\n\n### Karaoke Effect\n\nWhen karaoke mode is enabled, words also include `\\k` tags:\n\n```\n{\\k100}word\n```\n\nWhere `100` is the duration in centiseconds.\n\n### Shadow Effect\n\nWhen shadow is enabled, text includes `\\xshad` and `\\yshad` tags:\n\n```\n{\\xshad3\\yshad8}word\n```\n\nWhere:\n- `\\xshad3`: Horizontal shadow offset of 3 pixels\n- `\\yshad8`: Vertical shadow offset of 8 pixels\n\nThis creates a diagonal shadow that's more downward than sideways, as requested in the original specification.\n\n## Key Benefits\n\n- **🎯 Simple Structure**: Clean, flat project structure with all source files at the root\n- **🔌 Flexible Logging**: Injectable logger interface supporting multiple logging libraries\n- **⚡ Zero Dependencies**: Core library has no forced external dependencies\n- **📝 Structured Logging**: Built-in support for structured logging with key-value fields\n- **🛠️ Easy Integration**: Simple API that works with any Go project\n- **🎨 Rich Configuration**: Extensive customization options for fonts, colors, timing, and styling\n- **📊 Performance**: Optimized for performance with zero-allocation logging options\n- **🔧 Developer Friendly**: Comprehensive CLI with verbose logging and helpful error messages\n- **🔄 Consistent Defaults**: CLI flags automatically use configuration defaults, ensuring consistency\n- **🎨 Color Conversion**: Built-in functions to convert between hex and ASS color formats\n- **🌍 Encoding Support**: Built-in support for different text encodings (ANSI/Unicode)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nWe welcome contributions! Please follow these steps:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feat/amazing-feature`)\n3. Make your changes\n4. Add tests if applicable\n5. Run the test suite (`make test`)\n6. Commit your changes (`git commit -m 'feat: add some amazing feature'`)\n7. Push to the branch (`git push origin feat/amazing-feature`)\n8. Open a Pull Request\n\n### Development Guidelines\n\n- Follow Go best practices and conventions\n- Add tests for new functionality\n- Update documentation as needed\n- Use the provided Makefile targets for consistency\n- Ensure all tests pass before submitting\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkperreau%2Fwordsubgen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkperreau%2Fwordsubgen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkperreau%2Fwordsubgen/lists"}