{"id":50738243,"url":"https://github.com/hungv47/transcript-to-epub","last_synced_at":"2026-06-10T15:32:16.799Z","repository":{"id":361323663,"uuid":"1254043609","full_name":"hungv47/transcript-to-epub","owner":"hungv47","description":"Turn a YouTube video or raw timestamped transcript into a clean, readable EPUB book — speakers detected, timestamps stripped, cover generated.","archived":false,"fork":false,"pushed_at":"2026-05-30T04:40:19.000Z","size":12,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T06:20:50.883Z","etag":null,"topics":["claude-code","ebook","epub","pandoc","transcript","youtube"],"latest_commit_sha":null,"homepage":null,"language":"Python","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/hungv47.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":"2026-05-30T04:38:15.000Z","updated_at":"2026-05-30T04:40:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hungv47/transcript-to-epub","commit_stats":null,"previous_names":["hungv47/transcript-to-epub"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hungv47/transcript-to-epub","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hungv47%2Ftranscript-to-epub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hungv47%2Ftranscript-to-epub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hungv47%2Ftranscript-to-epub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hungv47%2Ftranscript-to-epub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hungv47","download_url":"https://codeload.github.com/hungv47/transcript-to-epub/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hungv47%2Ftranscript-to-epub/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34159250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["claude-code","ebook","epub","pandoc","transcript","youtube"],"created_at":"2026-06-10T15:32:11.726Z","updated_at":"2026-06-10T15:32:16.787Z","avatar_url":"https://github.com/hungv47.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# transcript-to-epub\n\nTurn a spoken-word transcript — from a **YouTube URL** or a **local timestamped\nmarkdown file** — into a calm, designed, **attributed** EPUB reading edition.\n\nEvery edition is **unofficial** and credits the original creators by full name at\nthe very beginning. It claims **no copyright** over the source material.\n\n\u003cimg width=\"1024\" height=\"1536\" alt=\"image\" src=\"https://github.com/user-attachments/assets/809a265e-e607-413f-a903-4516c9c5f1e4\" /\u003e\n\u003cimg width=\"1108\" height=\"830\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b4a14df1-a82f-4053-9fe3-deba4d1f6923\" /\u003e\n\nWorks as a standalone Python script or as a [Claude Code](https://docs.claude.com/en/docs/claude-code) skill (`SKILL.md` included).\n\n## Install\n\n```bash\nbrew install pandoc\npip3 install Pillow youtube-transcript-api\n# yt-dlp is optional but gives more reliable YouTube title/channel:\nbrew install yt-dlp\n```\n\nTo use it as a Claude Code skill, copy this folder into your skills directory\n(e.g. `~/.claude/skills/transcript-to-epub/`).\n\n## Requirements\n\n- `python3` and `pandoc` on PATH (pandoc builds the EPUB).\n- YouTube input: `youtube-transcript-api` (no API key needed).\n- Pillow cover (`--cover-method pillow`, or `auto` when Pillow is present): `Pillow`.\n- `yt-dlp` *(optional)* — better YouTube metadata; falls back to an HTML scrape.\n\n## Quick start\n\n```bash\npython3 scripts/build.py examples/sample-transcript.md\n```\n\nWrites `book.md` and `book.epub` next to the input.\n\n## Workflow\n\n```\ninput (YouTube URL | local .md)\n  -\u003e extract raw transcript\n  -\u003e clean to reading markdown (strip timestamps + \u003e\u003e markers, merge paragraphs)\n  -\u003e cover (Pillow auto | prompt loop | user-supplied | none)\n  -\u003e compile designed EPUB\n```\n\n1. **Input** — a YouTube URL (auto-fetches the transcript and channel name) or a\n   local timestamped transcript `.md`.\n2. **Extract** the raw transcript text.\n3. **Clean** — strip timestamps and `\u003e\u003e` speaker markers, merge into paragraphs.\n4. **Cover** — choose one path (see [Cover options](#cover-options)).\n5. **Compile** to a designed EPUB.\n\n**Outputs (both, always):**\n\n- `\u003coutput\u003e/book.md` — the assembled clean Markdown book (attribution + body).\n- `\u003coutput\u003e/book.epub` — the designed EPUB.\n\nThe CLI prints `Wrote: \u003cpath\u003e` for each. (A Pillow cover also writes `cover.png`.)\n\n## CLI\n\n```\npython3 scripts/build.py \u003cinput\u003e [options]\n```\n\n`\u003cinput\u003e` is a YouTube URL **or** a path to a local `.md` transcript.\n\n| Flag | Default | Meaning |\n|------|---------|---------|\n| `input` (positional) | — | YouTube URL or local `.md` transcript path |\n| `--title` | derived from filename or video title | Book title |\n| `--speakers` | auto-detected | Comma-separated speaker names; overrides the auto-detected byline |\n| `--source-url` | canonical YouTube URL for URL input; empty for file input | Link to the original; used in attribution + pandoc metadata |\n| `--cover` | — | Path to a user-supplied cover image (png/jpeg) |\n| `--cover-method` | `auto` | One of `auto`, `pillow`, `prompt`, `none` |\n| `--output` | input file's dir, or a title-slug dir for a YouTube URL | Output directory |\n| `--language` | `en` | Transcript language code (used for YouTube) |\n| `--css` | built-in stylesheet | Custom EPUB stylesheet |\n\n### Cover options\n\n`--cover-method` controls how the cover is produced:\n\n- `auto` — Pillow-generated brand cover if Pillow is installed; otherwise no cover.\n- `pillow` — force the Pillow-generated brand cover.\n- `prompt` — print a ready-to-paste, brand-aligned AI image-generation prompt to\n  stdout, then build **without** a cover. Generate the art in any image tool and\n  re-run with `--cover \u003cfile\u003e`.\n- `none` — no cover.\n\nYou can always skip the methods above and pass your own image with\n`--cover path/to/cover.png`.\n\n## Attribution \u0026 copyright\n\nThis is a hard requirement of the tool, not an option.\n\nEvery book **always** credits the original creators by full name at the very\nbeginning, before any transcript content. The editions are **unofficial** and\n**claim no copyright** over the source material.\n\nEach book opens with an attribution front-matter block, wrapped in\n`\u003c!-- t2e:attribution:start --\u003e` / `\u003c!-- t2e:attribution:end --\u003e` markers (pandoc\ndrops these HTML comments from the rendered EPUB):\n\n- H1 title\n- credit line: `An unofficial reading edition of a conversation by \u003ccreators\u003e.`\n- source line: `Original source: \u003csource_url\u003e` (omitted only when the URL is unknown)\n- a blockquote disclaimer: this edition is unofficial; all rights to the original\n  material belong to the original creators; this edition claims no copyright over\n  the source; an invitation to support the creators at the source URL.\n\nRules the tool enforces:\n\n- Credit is **never** silently dropped.\n- If creators are unknown, the byline falls back to `the original creators`.\n- If the URL is unknown, only the URL line is omitted.\n- The same facts are written to EPUB metadata: `author=\u003ccreators\u003e` plus a\n  `rights`/`description` string naming the source and the non-ownership statement.\n- The block appears in **both** the Markdown output and the EPUB.\n- Re-running on an already-assembled `book.md` is idempotent — the attribution\n  block is not duplicated.\n\n## Examples\n\n### YouTube URL\n\nThe canonical `https://www.youtube.com/watch?v=\u003cid\u003e` source URL is filled in\nautomatically; the channel name becomes the creator byline.\n\n```bash\npython3 scripts/build.py \"https://www.youtube.com/watch?v=VIDEO_ID\" \\\n  --title \"The Craft Conversation\" \\\n  --cover-method auto\n```\n\nOverride the byline if you want named speakers instead of the channel:\n\n```bash\npython3 scripts/build.py \"https://www.youtube.com/watch?v=VIDEO_ID\" \\\n  --speakers \"Ada Lovelace, Grace Hopper\"\n```\n\n### Local transcript with the cover-prompt loop\n\n```bash\n# 1. Print an AI image prompt and produce a no-cover build:\npython3 scripts/build.py examples/sample-transcript.md \\\n  --speakers \"Ada Lovelace, Grace Hopper\" \\\n  --source-url \"https://example.com/talk\" \\\n  --cover-method prompt\n\n# Copy the printed prompt into your AI image tool of choice,\n# then save the result as cover.png.\n\n# 2. Re-run with the generated image to get the final cover:\npython3 scripts/build.py examples/sample-transcript.md \\\n  --speakers \"Ada Lovelace, Grace Hopper\" \\\n  --source-url \"https://example.com/talk\" \\\n  --cover cover.png\n```\n\n## Input format\n\nA local transcript is markdown with an H1 title and timestamped `\u003e\u003e`-marked\nturns. See `examples/sample-transcript.md`. The cleaner understands several line\nshapes and falls through gracefully:\n\n```\n**00:01:23**: \u003e\u003e Alice: A timestamped speaker line.\n**00:01:27**: A continuation line (timestamp only).\n\u003e\u003e Bob: A speaker line without a timestamp.\nPlain prose with no markers is kept too.\n```\n\nTimestamps (`**HH:MM:SS**`) and `\u003e\u003e` markers are stripped during cleaning; turns\nare merged into reading paragraphs.\n\n## Supported YouTube URLs\n\n`watch?v=`, `youtu.be/`, `/embed/`, `/shorts/`, or a bare 11-character video ID.\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhungv47%2Ftranscript-to-epub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhungv47%2Ftranscript-to-epub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhungv47%2Ftranscript-to-epub/lists"}