Metadata-Version: 2.4
Name: webvtt-to-markdown
Version: 0.9.0
Summary: WebVTT to Markdown converter with MarkItDown plugin integration.
Author: GreenJesterAt
License-Expression: Apache-2.0
Project-URL: Repository, https://github.com/GreenJesterAt/webvtt-to-markdown
Project-URL: Issues, https://github.com/GreenJesterAt/webvtt-to-markdown/issues
Keywords: webvtt,vtt,markdown,transcript,markitdown,markitdown-plugin
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: charset-normalizer>=3.0
Requires-Dist: markitdown>=0.1.5
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: twine>=6.0; extra == "dev"
Dynamic: license-file

# webvtt-to-markdown

WebVTT to Markdown converter with a MarkItDown plugin entry point.

Findable as a MarkItDown plugin via `#markitdown-plugin`.

## Scope

- Supports `.vtt` transcript input only
- Prioritizes Microsoft Teams-style WebVTT cues
- Falls back to a generic WebVTT generation source when no more specific source is detected
- Works as a MarkItDown plugin via the `markitdown.plugin` entry point

## Installation

```bash
pip install webvtt-to-markdown
```

## Usage

Standalone Python usage:

```python
from webvtt_to_markdown import transcript_to_markdown

markdown = transcript_to_markdown(vtt_text)
```

List installed plugins:

```bash
markitdown --list-plugins
```

Convert a Teams transcript with plugins enabled:

```bash
markitdown -p input.vtt
```

Write the output to a file:

```bash
markitdown -p input.vtt -o output.md
```

## Current behavior

- `ms_teams_scheduled`
  - recognizes Teams-style identifiers like `.../xxx-y`
  - groups transcript fragments by `xxx`
  - uses the `y=0` cue as the block header when available
- `ms_teams_event`
  - handles Teams-style identifiers without `<v ...>` speaker tags
- `zoom_scheduled`
  - expects numeric identifiers starting at `1`
  - expects single-line cues with textual speaker prefixes
  - supports optional whitespace around `:`
  - uses a document-wide first-colon or last-colon split depending on the cue sample
- `zoom_event`
  - handles numeric single-line cues without speaker prefixes
  - may also match a single numeric cue
- `meeting_novoicetag`
  - handles meeting-style textual speaker prefixes without `<v ...>` tags
  - requires speaker marking to be consistent; partially marked files fall back to `generic_webvtt`
- `generic_webvtt`
  - preserves cue order
  - uses `<v ...>` speaker tags when present
  - also handles cues without identifiers
  - renders `NOTE` blocks as Markdown blockquotes
  - ignores `STYLE` blocks

After generation-source rendering, a separate postprocessing step:

- stitches consecutive blocks from the same recognized speaker
- prevents stitching across list-like blocks and `NOTE` blocks
- applies text reflow for meeting-like generation sources
- leaves `generic_webvtt` intentionally conservative

Generation sources are loaded softly from `gen_src_*` modules inside the package. Detection scores all registered generation sources on a sampled prefix of the parsed document, then picks the highest `confidence`; ties are broken by the module `importance`.

## Supported WebVTT text tags

- `<b>...</b>` becomes `**...**`
- `<i>...</i>` becomes `*...*`
- `<u>...</u>` becomes `_..._`
- `<c.class>...</c>` keeps only the inner text
- `<lang xx[-YY]>...</lang>` keeps only the inner text
- `<ruby>...</ruby>` becomes `( ... )` style inline ruby text with spacing normalized around it
- inline WebVTT timestamp tags like `<00:00:04.000>` are removed
- malformed inline tags are left visible instead of being guessed or silently repaired

Voice tags such as `<v Speaker>...</v>` and `<v.team Speaker>...</v>` are used to extract speaker names for headings.

Empty textual speaker lines such as `Speaker:` are ignored and not written to Markdown.

## Encoding

- Input files may be provided with or without BOM.
- The plugin tries to detect the input charset when no charset hint is provided.
- The standard MarkItDown CLI writes output as UTF-8.
- For this plugin, the repository Golden outputs are stored as UTF-8 with BOM.

### Strict vs lazy decoding

- Default behavior is strict: undecodable input raises an error.
- The plugin also supports a Python-API-only lazy mode via `charset_lazy=True`.
- In lazy mode, undecodable characters are replaced with `[ENC?]`.

Example with the Python API:

```python
from markitdown import MarkItDown

converter = MarkItDown(enable_plugins=True)
result = converter.convert("input.vtt", charset_lazy=True)
print(result.markdown)
```

You can also force a specific generation source through the Python API:

```python
from markitdown import MarkItDown

converter = MarkItDown(enable_plugins=True)
result = converter.convert("input.vtt", generation_source="generic_webvtt")
print(result.markdown)
```

## Development

Project-specific process notes:

- [Development Workflow](docs/development_workflow.md)
- [Testing Policy](docs/testing_policy.md)

Install the project and development tools into the active environment:

```bash
pip install -e .[dev]
```

Run tests:

```bash
pytest
```

Current test status:

```text
92 passed
```
