{"id":50964357,"url":"https://github.com/sinedied/am2mid","last_synced_at":"2026-06-18T18:01:42.150Z","repository":{"id":363547358,"uuid":"1254608209","full_name":"sinedied/am2mid","owner":"sinedied","description":"YouTube → isolated melody stem → MIDI pipeline for trance \u0026 co. (yt-dlp + Demucs + Basic Pitch)","archived":false,"fork":false,"pushed_at":"2026-05-30T20:48:58.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-09T11:31:29.218Z","etag":null,"topics":["audio-to-midi","basic-pitch","demucs","midi","music-information-retrieval","python-cli","stem-separation","trance","youtube","yt-dlp"],"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/sinedied.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-30T19:33:03.000Z","updated_at":"2026-05-30T20:49:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sinedied/am2mid","commit_stats":null,"previous_names":["sinedied/am2mid"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sinedied/am2mid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinedied%2Fam2mid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinedied%2Fam2mid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinedied%2Fam2mid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinedied%2Fam2mid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sinedied","download_url":"https://codeload.github.com/sinedied/am2mid/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinedied%2Fam2mid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34501482,"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-18T02:00:06.871Z","response_time":128,"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":["audio-to-midi","basic-pitch","demucs","midi","music-information-retrieval","python-cli","stem-separation","trance","youtube","yt-dlp"],"created_at":"2026-06-18T18:01:41.145Z","updated_at":"2026-06-18T18:01:42.145Z","avatar_url":"https://github.com/sinedied.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# am2mid\n\n**am2mid** = *Audio Melody to MIDI*. Tiny CLI that turns a YouTube track into a melody MIDI file (and/or an isolated melody stem you can drag into [NeuralNote](https://github.com/DamRsn/NeuralNote) or any other audio→MIDI VST).\n\nPipeline:\n\n```\nYouTube URL ──► yt-dlp ──► (optional trim) ──► Demucs (htdemucs) ──► melody stem ──► Basic Pitch ──► .mid\n```\n\n## Requirements\n\nSystem tools (install once):\n\n```bash\nbrew install ffmpeg\n```\n\nPython deps are managed with [uv](https://docs.astral.sh/uv/):\n\n```bash\nuv sync\n```\n\nThat installs `yt-dlp`, `demucs`, `basic-pitch`, etc. into a local `.venv`.\n\n## Usage\n\nSingle track (default: all stems saved as wav, MIDI generated for `other`):\n\n```bash\nuv run am2mid \"https://www.youtube.com/watch?v=zGDzdps75ns\" \\\n  --range \"1:05-2:05\" \\\n  --out ./output\n```\n\nSkip transcription if you plan to use NeuralNote VST instead:\n\n```bash\nuv run am2mid \"\u003cURL\u003e\" --range \"1:05-2:05\" --no-midi\n```\n\nTranscribe every stem (not just `other`):\n\n```bash\nuv run am2mid \"\u003cURL\u003e\" --range \"1:05-2:05\" --midi-all\n```\n\nQuantize the transcription to a 1/16th grid (BPM auto-detected from the drums stem):\n\n```bash\nuv run am2mid \"\u003cURL\u003e\" --range \"1:05-2:05\" --quantize 1/16\n```\n\nForce a specific BPM and also keep the stem .wav files:\n\n```bash\nuv run am2mid \"\u003cURL\u003e\" --range \"1:05-2:05\" --quantize 1/16 --bpm 138 --with-stems\n```\n\nUse the 6-stem model when the lead is a recognizable guitar/piano:\n\n```bash\nuv run am2mid \"\u003cURL\u003e\" --range \"1:05-2:05\" --model htdemucs_6s --stem piano\n```\n\nBatch mode from a YAML file (see [`example.yaml`](./example.yaml)):\n\n```bash\nuv run am2mid --batch example.yaml\n```\n\n### Options\n\n| Flag | Default | Description |\n|------|---------|-------------|\n| `url` (positional) | — | YouTube URL (omit if using `--batch`). |\n| `--range`, `-r` | full track | Melody window, format `MM:SS-MM:SS`. |\n| `--batch`, `-b` | — | YAML file with a list of songs. |\n| `--out`, `-o` | `./output` | Output directory. |\n| `--name`, `-n` | from video title | Folder name (single-URL mode). |\n| `--stem` | `other` | Which stem gets transcribed to MIDI. All stems are always saved as `.wav`. |\n| `--model` | `htdemucs` | Demucs model (use `htdemucs_6s` for guitar/piano stems). |\n| `--midi-all` | off | Transcribe every stem, not just `--stem`. |\n| `--no-midi` | off | Skip basic-pitch (use a VST instead). |\n| `--quantize`, `-q` | off | Snap MIDI notes to a grid. Subdivision as `1/16`, `1/8`, `16`… (powers of 2, 1–32). Writes a sidecar `*.q\u003cN\u003e.mid`. |\n| `--bpm` | `auto` (when `--quantize`) | Tempo. Either a number (`138`) or `auto` to detect from the drums stem. |\n| `--with-stems`, `-s` / `--no-stems` | on | Save the chosen melody stem `.wav` (only `--stem`). |\n| `--all-stems`, `-a` | off | Save ALL stems as `.wav` (for A/B comparison). |\n| `--with-full` / `--no-full` | on | Save the un-separated full audio as `midi/stems/\u003cname\u003e_full.wav`. |\n| `--bpm-range` | `120-160` | Window used to fold auto-detected BPM (e.g. 70 → 140). Format `MIN-MAX`. Ignored when `--bpm` is explicit. |\n| `--force`, `-f` | off | Overwrite existing midi/stem files without prompting. |\n\n### Output layout\n\n```\noutput/\n  midi/\n    \u003cname\u003e.mid                    # primary MIDI (the --stem one, default 'other')\n    \u003cname\u003e.q16.mid                # quantized sidecar (if --quantize)\n    \u003cname\u003e_drums.mid              # extra MIDIs when --midi-all\n      stems/                        # created when --with-stems / --all-stems / --with-full\n        \u003cname\u003e_full.wav             # un-separated audio (default on)\n        \u003cname\u003e_other.wav            # chosen melody stem (default on)\n        \u003cname\u003e_drums.wav            # other stems only with --all-stems\n        ...\n  .work/\u003cname\u003e/                   # raw download + demucs intermediates\n```\n\n`\u003cname\u003e` is your `--name`, or the YouTube title sanitized into a readable, filesystem-safe form.\n\n### YAML batch + global defaults + per-song overrides\n\n`example.yaml`:\n```yaml\ndefaults:                     # any CLI flag, applied to every song; CLI overrides win\n  quantize: 1/16\n  bpm: auto                   # auto-detected, folded into bpm_range\n  bpm_range: 120-160          # trance-friendly window\n  with_full: true\n\nsongs:\n  - url: https://www.youtube.com/watch?v=...\n      name: my-track\n      range: \"1:05-2:05\"\n  - url: https://www.youtube.com/watch?v=...\n      name: tricky-tempo\n      bpm: 140                  # per-song override beats defaults + CLI\n      all_stems: true           # also dump every stem just for this track\n```\n\nRun with:\n```bash\nuv run am2mid --batch example.yaml\n# Override a default at runtime (per-song overrides still win):\nuv run am2mid --batch example.yaml --no-full\n```\n\n### Auto BPM folding\n\n`auto` (the default when `--quantize` is set) runs librosa's beat tracker on the **drums** stem (cleaner than the full mix). The raw estimate is then folded into `--bpm-range` (default `120-160`) by ×2 / ÷2 multiples, so half-time detections like 70 BPM become 140 BPM. Explicit `--bpm 138` is never altered.\n\n## Tips for trance leads\n\n- The synth lead almost always lands in the `other` stem of `htdemucs` (the default 4-stem model). If the track has a clear guitar or piano lead, switch to the 6-stem model with `--model htdemucs_6s --stem guitar` (or `piano`).\n- Pick a clean melodic section (no vocal chops, no big build-up FX) with `--range` — Basic Pitch is much happier with 30–60s of clear melody than the whole 7-minute track.\n- For best quality, keep the stem (`--keep-stem`) and run it through [NeuralNote](https://github.com/DamRsn/NeuralNote) in your DAW, then nudge octaves and quantize manually.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinedied%2Fam2mid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsinedied%2Fam2mid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinedied%2Fam2mid/lists"}