PythonとAIでYouTubeの音声をMIDIに自動変換する方法【Google Colab・Basic Pitch】
はじめに
YouTubeで公開されている楽曲を聴いていて、その演奏をMIDIデータとして取り出せないかと考えたことがある。
MIDIデータがあれば、楽曲に含まれる音符をピアノロールで確認したり、DAWで編集したり、シンセサイザーの演奏データとして利用したりできる。
今回は、PythonとSpotifyが公開している音程推定AIのBasic Pitchを使い、YouTube動画の音声をMIDIファイルに変換するプログラムを作成する。
実行環境にはGoogle Colabを使用するため、ローカルPCにPythonの開発環境を構築する必要はない。
本記事では、以下の処理を自動化する。
YouTubeのURLを指定する
yt-dlpで動画から音声を取得する
FFmpegで音声をWAV形式に変換する
Basic Pitchで音声全体を解析する
音程・発音開始時刻・音の長さを推定する
MIDIファイルとCSVファイルを生成する
Google Colabからファイルをダウンロードする
ただし、音声からすべての音符を完全に復元できるわけではない。特に複数の楽器が同時に演奏される楽曲では、音程の検出漏れや誤検出が発生する。
1. 使用する技術
今回のプログラムでは、以下のライブラリとツールを使用する。
技術
役割
Python
プログラム全体の制御
Google Colab
Pythonの実行環境
yt-dlp
YouTube動画からの音声取得
FFmpeg
音声形式の変換
Spotify Basic Pitch
AIによる音程推定
TensorFlow Lite
学習済みモデルの推論
uv
Python実行環境とライブラリの管理
setuptools
一部の旧ライブラリとの互換性確保
1.1 yt-dlpとは
yt-dlpは、動画配信サイトなどのメディアを取得するためのオープンソースソフトウェアである。
今回のプログラムでは、YouTube動画から音声ストリームを取得するために使用する。
動画によってはWebMやM4A形式などで保存されるため、後続の解析処理に向けてFFmpegでWAV形式に変換する。
なお、YouTubeのアクセス制限などにより取得できない動画もある。利用する際は、ダウンロードと変換が許可されている音源を対象とする。
1.2 Spotify Basic Pitchとは
Basic PitchはSpotifyが公開している、音声をMIDIに変換するための機械学習モデルである。
通常の音声ファイルには、時間とともに変化する音圧に対応したサンプル値が格納されている。
一方、MIDIは音声の波形そのものではなく、音符に関する情報を記録する。
主な情報は以下のとおりである。
MIDIノート番号
音符の発音開始時刻
音符の終了時刻
ベロシティ
ピッチベンド
Basic Pitchは音声信号を解析し、こうした情報を推定する。
複数の音程が同時に鳴る場合にも対応しているが、特に単一楽器の録音を対象とした音程推定に適している。
1.3 TensorFlow Liteとは
TensorFlow Liteは、学習済みの機械学習モデルを比較的軽量な実行環境で推論するための仕組みである。
Basic PitchにはTensorFlow、TensorFlow Lite、ONNXなど複数のモデル形式が用意されている。
今回はGoogle ColabのPython環境との互換性を考慮し、Python 3.10とTensorFlow Liteを組み合わせる。
2. 音声からMIDIを生成する仕組み
ここでは、音声信号を音符データに変換する基本的な考え方を説明する。
2.1 音声信号を数値として扱う
デジタル音声は、一定の時間間隔で音声信号を標本化したデータである。
例えば、サンプリング周波数が22,050 Hzの場合、1秒間に22,050個のサンプルを記録する。
離散時間の音声信号を次のように表す。
x[n] = x\left(\frac{n}{f_s}\right)
ここで、
x[n] は離散時間信号
n はサンプル番号
f_s はサンプリング周波数
である。
音声の音程を解析するには、この時間領域の信号に含まれる周期的な特徴を調べる必要がある。
2.2 短時間フーリエ変換
音声の周波数成分を時間ごとに調べる代表的な手法が、短時間フーリエ変換(STFT)である。
X(m,k)=
\sum_{n=0}^{N-1}
x[n+mH]w[n]
e^{-j2\pi kn/N}
各記号は以下を表す。
x[n] は音声サンプル
w[n] は窓関数
N はFFTの窓長
H はホップ長
m は時間フレーム
k は周波数ビン
STFTによって、音声に含まれる周波数成分の時間変化を調べられる。
ただし、フーリエ変換によって得られた周波数成分を、そのままMIDIノートに変換できるわけではない。
実際の楽器音には基本周波数に加えて倍音が含まれ、複数の楽器音が重なる場合もある。
そのため、音程推定には複数の周波数成分の関係や、時間方向の特徴を考慮する必要がある。
なお、Basic Pitchの内部処理は単純なSTFTのピーク検出だけで構成されているわけではなく、学習済みニューラルネットワークを使用している。
2.3 周波数とMIDIノート番号
平均律では、音の周波数とMIDIノート番号の間に次の関係がある。
f=440\times 2^{\frac{n-69}{12}}
ここで、
f は周波数(Hz)
n はMIDIノート番号
440 HzはA4の基準周波数
である。
この式を変形すると、
n=69+12\log_2\left(\frac{f}{440}\right)
となる。
例えば、440 Hzの音に対応するMIDIノート番号は69である。
音名
周波数の目安
MIDIノート番号
C4
261.63 Hz
60
D4
293.66 Hz
62
E4
329.63 Hz
64
A4
440.00 Hz
69
C5
523.25 Hz
72
ただし、音声からMIDIを生成する場合には音高だけでは不十分である。
音符がいつ始まったのか、いつ終わったのかも推定しなければならない。
2.4 AIによる音符イベントの推定
Basic Pitchは音声から、音の立ち上がり、継続状態、ピッチ変化などを推定する。
これらの情報を利用して、音符イベントを生成する。
例えば、次のような音符情報が得られたとする。
開始時刻
終了時刻
音高
0.00秒
0.50秒
C4
0.50秒
1.00秒
E4
1.00秒
1.50秒
G4
これらをMIDIファイルに保存すれば、DAWなどでピアノロールとして表示できる。
3. Google Colabでプログラムを実行する
実行環境はGoogle Colabを使用する。
colab.research.google.com
新しいノートブックを作成し、次のコードを1つのコードセルに貼り付ける。
冒頭の YOUTUBE_URL に変換したいYouTube動画のリンクを指定する。
以下では、実装例としてYouTubeのURLを設定済みにしている。
4. Pythonプログラム全文
============================================================
YouTube to MIDI Converter
Google Colab用
#
YouTubeの音声をAIで解析してMIDIに変換する
#
使用ライブラリ
yt-dlp
FFmpeg
Spotify Basic Pitch
TensorFlow Lite
#
出力
MIDIファイル (.mid)
音符情報 (.csv)
============================================================
============================================================
0. YouTubeのリンクを設定
============================================================
YOUTUBE_URL = "youtu.be"
別の動画に変更する場合はURLを書き換える
============================================================
1. 必要なライブラリを準備
============================================================
import os
import sys
import subprocess
import tempfile
from pathlib import Path
from google.colab import files
def run_command(command):
"""コマンドを実行し、実行結果を表示する"""
result = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True
)
print(result.stdout)
if result.returncode != 0:
raise RuntimeError(
f"コマンド実行失敗: {result.returncode}"
)
return result
print("ライブラリをインストール中...")
run_command([
sys.executable,
"-m", "pip",
"install",
"-q",
"-U",
"yt-dlp[default]",
"uv"
])
============================================================
2. Denoを準備
============================================================
print("YouTube音声取得環境を準備中...")
DENO_PATH = (
Path.home() / ".deno" / "bin" / "deno"
)
if not DENO_PATH.exists():
run_command([
"bash",
"-c",
"curl -fsSL deno.land | sh"
])
os.environ["PATH"] = (
str(DENO_PATH.parent)
- os.pathsep
- os.environ["PATH"]
)
print("Deno準備完了")
============================================================
3. URLの確認
============================================================
if not YOUTUBE_URL.startswith((
"youtube.com",
"youtube.com",
"youtu.be",
"music.youtube.com"
)):
raise ValueError(
"YouTubeのURLを確認してください"
)
============================================================
4. 作業フォルダを作成
============================================================
WORK_DIR = Path(
tempfile.mkdtemp(
prefix="youtube_midi_",
dir="/content"
)
)
OUTPUT_DIR = WORK_DIR / "output"
OUTPUT_DIR.mkdir(
parents=True,
exist_ok=True
)
print("作業フォルダ:", WORK_DIR)
============================================================
5. YouTubeから音声を取得
============================================================
print("YouTubeから音声を取得中...")
run_command([
sys.executable,
"-m", "yt_dlp",
"--no-playlist",
"-f", "bestaudio/best",
"-o",
str(WORK_DIR / "source.%(ext)s"),
YOUTUBE_URL
])
============================================================
6. ダウンロードした音声を確認
============================================================
audio_files = [
p for p in WORK_DIR.glob("source.*")
if p.is_file()
and p.suffix not in (
".part",
".ytdl"
)
]
if not audio_files:
raise RuntimeError(
"YouTube音声の取得に失敗しました"
)
AUDIO_PATH = audio_files[0]
print("音声取得完了")
print("ファイル:", AUDIO_PATH.name)
============================================================
7. 音声をWAV形式に変換
============================================================
print("WAV形式に変換中...")
WAV_PATH = WORK_DIR / "audio.wav"
run_command([
"ffmpeg",
"-y",
"-hide_banner",
"-loglevel", "error",
"-i", str(AUDIO_PATH),
"-vn",
"-ac", "1",
"-ar", "22050",
"-c:a", "pcm_s16le",
str(WAV_PATH)
])
if not WAV_PATH.exists():
raise RuntimeError(
"WAVファイルが生成されませんでした"
)
print("WAV変換完了")
============================================================
8. Basic Pitchの実行環境を設定
============================================================
print("AI音程推定環境を準備中...")
Python 3.10を使用
setuptoolsを固定してpkg_resourcesエラーを対策
TensorFlow Lite版を使用
BASIC_PITCH_COMMAND = [
"uv",
"run",
"--no-project",
"--python", "3.10",
"--with", "setuptools==80.9.0",
"--with", "basic-pitch==0.4.0",
"--with", "tflite-runtime==2.14.0",
"--with", "numpy<2",
"--",
"basic-pitch",
str(OUTPUT_DIR),
str(WAV_PATH),
"--model-serialization",
"tflite",
"--save-note-events"
]
============================================================
9. AIで音声全体を解析
============================================================
print("================================")
print("AIで音声全体を解析中...")
print("================================")
result = subprocess.run(
BASIC_PITCH_COMMAND,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True
)
print(result.stdout)
if result.returncode != 0:
raise RuntimeError(
"Basic PitchによるMIDI変換に失敗しました。"
"上の実行ログを確認してください。"
)
print("AI音程解析完了")
============================================================
10. MIDIファイルを確認
============================================================
midi_files = sorted(
OUTPUT_DIR.glob("*.mid")
)
if not midi_files:
raise RuntimeError(
"MIDIファイルが生成されませんでした"
)
print("MIDI変換成功")
for midi in midi_files:
print(
"MIDIファイル:",
midi.name
)
============================================================
11. MIDIファイルをダウンロード
============================================================
print("MIDIファイルをダウンロード中...")
for midi in midi_files:
files.download(
str(midi)
)
============================================================
12. CSV形式の音符情報もダウンロード
============================================================
csv_files = sorted(
OUTPUT_DIR.glob("*.csv")
)
for csv_file in csv_files:
files.download(
str(csv_file)
)
============================================================
13. 完了
============================================================
print("================================")
print("YouTube to MIDI 変換完了")
print("================================")
print("保存先:", OUTPUT_DIR)
print("生成されたMIDI:")
for midi in midi_files:
print(midi.name)
print("すべての処理が終了しました")
このコードはGoogle Colab上での動作を想定しているが、全処理の実行検証は完了していない。PythonパッケージやYouTubeの仕様変更によって修正が必要になる可能性がある。
5. プログラムの解説
5.1 YouTubeのURLを設定する
プログラム冒頭の次の部分で、変換対象の動画を指定する。
YOUTUBE_URL = "youtu.be"
URLはPythonの文字列として指定する必要がある。
Markdownのリンク記法をそのままPythonコードに貼り付けると、SyntaxErrorが発生するので注意する。
5.2 yt-dlpで音声を取得する
run_command([
sys.executable,
"-m", "yt_dlp",
"--no-playlist",
"-f", "bestaudio/best",
"-o", str(WORK_DIR / "source.%(ext)s"),
YOUTUBE_URL
])
この部分では、yt-dlpを使ってYouTube動画の音声を取得している。
--no-playlist はプレイリスト全体をダウンロードしないための指定である。
-f bestaudio/best は音声を優先して取得するための指定である。
また、ファイル名の拡張子は取得したフォーマットによって決まる。
例えば、WebM形式の音声が取得された場合は、source.webmというファイルが生成される。
5.3 FFmpegでWAV形式に変換する
run_command([
"ffmpeg",
"-y",
"-hide_banner",
"-loglevel", "error",
"-i", str(AUDIO_PATH),
"-vn",
"-ac", "1",
"-ar", "22050",
"-c:a", "pcm_s16le",
str(WAV_PATH)
])
この処理では、取得した音声をWAV形式に変換する。
各オプションの意味は以下のとおりである。
オプション
意味
-i
入力ファイルの指定
-vn
動画ストリームを除外
-ac 1
モノラル音声へ変換
-ar 22050
サンプリング周波数22,050 Hz
-c:a pcm_s16le
16ビット符号付きPCMで保存
-y
既存ファイルを上書き
ここでサンプリング周波数を22,050 Hzにしているが、これだけで音程推定が完成するわけではない。
次のBasic Pitchによる推論処理が必要になる。
なお、Basic Pitch側では必要に応じて音声の再サンプリングなどが行われる。
5.4 Basic Pitchを実行する
MIDI変換の中心となるのが、次の部分である。
BASIC_PITCH_COMMAND = [
"uv", "run",
"--no-project",
"--python", "3.10",
"--with", "setuptools==80.9.0",
"--with", "basic-pitch==0.4.0",
"--with", "tflite-runtime==2.14.0",
"--with", "numpy<2",
"--",
"basic-pitch",
str(OUTPUT_DIR),
str(WAV_PATH),
"--model-serialization", "tflite",
"--save-note-events"
]
Google Colabの標準Python環境とBasic Pitchの対応バージョンが一致しない場合がある。
そのため、uvを使ってPython 3.10の独立した実行環境を用意している。
--model-serialization tflite は、TensorFlow Lite形式のモデルを使用するための指定である。
--save-note-events を指定すると、MIDIに加えて推定した音符イベントをCSV形式でも出力できる。
5.5 MIDIファイルをダウンロードする
midi_files = sorted(
OUTPUT_DIR.glob("*.mid")
)
for midi in midi_files:
files.download(str(midi))
Basic Pitchが生成したMIDIファイルを取得し、Google Colabのダウンロード機能で保存している。
生成されたファイルは、MIDI対応のDAWやピアノロール表示ソフトで読み込める。
6. 実行時に発生したエラーと対策
今回の実装では、Python環境とライブラリの互換性について注意が必要だった。
6.1 Pythonのバージョン問題
Google ColabのPythonバージョンは更新されることがある。
一方、今回使用するBasic Pitch 0.4.0は、Python 3.10や3.11を含む環境を対象としている。
対応していないPythonバージョンに直接インストールすると、依存ライブラリの解決で失敗する可能性がある。
この問題に対して、今回のコードでは次の指定を使用している。
"uv", "run",
"--no-project",
"--python", "3.10",
ColabのPython自体を変更せず、Basic Pitchだけを別のPython環境で実行する方法である。
6.2 pkg_resourcesが見つからない問題
実装中、次のエラーが発生した。
ModuleNotFoundError:
No module named 'pkg_resources'
これは、Basic Pitchが依存するresampyがpkg_resourcesを読み込もうとした際に発生したエラーである。
pkg_resourcesは従来setuptoolsに含まれていたが、新しいsetuptoolsでは削除されている。
そこで、今回のコードでは次のようにバージョンを固定した。
"--with", "setuptools==80.9.0",
この指定は旧APIとの互換性を確保するための対策である。将来的にはライブラリ側の更新に合わせた対応が望ましい。
6.3 TensorFlow関連の警告
実行時に次のような警告が表示されることがある。
Tensorflow is not installed.
Coremltools is not installed.
onnxruntime is not installed.
Basic Pitchが複数の推論エンジンに対応していることに関連する警告である。
今回のプログラムではTensorFlow Liteを明示的に使用しているため、これらの警告だけで必ずしも変換失敗を意味するわけではない。
ただし、TensorFlow Lite側のモデル読み込みに失敗している場合は、別途エラー内容の確認が必要である。
6.4 YouTubeの音声を取得できない場合
yt-dlpを使用していても、すべての動画を取得できるとは限らない。
例えば、動画のアクセス制限、YouTube側の仕様変更、Colabからのアクセス制限などが原因となることがある。
この場合は、yt-dlpの実行ログを確認する。
今回のコードではDenoをインストールし、YouTubeのJavaScript処理に対応する構成としているが、取得成功を保証するものではない。
7. 変換精度の限界
音声からMIDIへの変換は、音響信号から音符を推定する問題である。
そのため、元のMIDIファイルを完全に復元する処理とは異なる。
7.1 単一楽器の演奏
ピアノやギターなどの単一楽器を録音した音源では、音程の推定が比較的行いやすい。
特に、録音状態が良く、音符の立ち上がりが明確な場合は解析しやすくなる。
7.2 複数の楽器による演奏
バンド演奏では、ギター、ベース、ドラム、ボーカルなどが同時に鳴る。
この場合、各楽器の周波数成分が重なり、音程の推定が難しくなる。
例えば、エレキギターの倍音が別の音符として誤認識されることがある。
また、ドラムのような非調波的な音は、通常の音高を持つ楽器とは性質が異なるため、Basic Pitchだけで正確なドラムMIDIを生成することは難しい。
7.3 MIDIは元の音色を保存しない
MIDIファイルには、元の音声波形がそのまま保存されるわけではない。
そのため、エレキギターの音声をMIDIに変換しても、ディストーションの音色やアンプの特性まで再現されるわけではない。
MIDIから音を再生するには、別途シンセサイザーや音源が必要になる。
8. 今後の拡張
今回のプログラムは、YouTubeの音声を一括してMIDIに変換する構成である。
さらに精度を高めたい場合は、音源分離技術を組み合わせる方法が考えられる。
例えば、Demucsなどの音源分離モデルを使って楽曲をボーカル、ドラム、ベース、その他の成分に分離し、その後で音程推定を行う方法である。
音源分離そのものにも誤差はあるが、混合音源をそのまま解析する場合とは異なるアプローチが可能になる。
また、次のような拡張も考えられる。
楽器別MIDIファイルの生成
MIDIのピアノロール可視化
ノートイベントの重複除去
BPM推定と音符のクオンタイズ
MIDIノート番号と周波数の比較
FFT・スペクトログラム・MIDIの同時可視化
特に、音声のスペクトログラムとMIDIのピアノロールを比較できれば、デジタル信号処理の学習教材としても利用できる。
9. まとめ
今回は、PythonとSpotify Basic Pitchを使い、YouTube動画の音声全体をMIDIデータに変換するプログラムを実装した。
プログラムでは、yt-dlpによる音声取得、FFmpegによるWAV変換、Basic Pitchによる音程推定、MIDIとCSVの出力を組み合わせている。
また、Google ColabのPython環境との互換性を考慮し、uvを使ってPython 3.10の実行環境を用意した。
音声をMIDIに変換する技術は、単なる楽曲の採譜だけでなく、音響信号処理、機械学習、デジタルシンセサイザー、音楽情報検索などとも関係している。
今回のプログラムは、その仕組みを実際の音源を使って学ぶための出発点になる。
なお、コードはColabでの一連の動作確認が完了していないため、実際の利用時には生成結果と実行ログを確認する必要がある。
参考資料
Spotify Basic Pitch - GitHub
Basic Pitch - PyPI
yt-dlp - GitHub
FFmpeg Documentation
Google Colab
uv Documentation
TensorFlow Lite
I built a free YouTube/SoundCloud downloader for Windows that runs entirely on your PC
Every "download a YouTube video" website looks the same: ads, pop-ups, and a big green button that takes you somewhere you did not want to go. And if you need a different site (SoundCloud, Vimeo, TikTok...), you need a different downloader.
I wanted one place where I could drop any link and get a normal file. So I built Universal Downloader, a free, open-source Windows app on top of yt-dlp.
!Pasting a link and picking a quality
What it does
- Paste a link, get a file. YouTube, SoundCloud, Vimeo, TikTok, Instagram and 1000+ other sites that yt-dlp supports. MP4 from 144p to 4K, MP3 with cover art and tags, or M4A without re-encoding.
- Playlists and queues. Paste a playlist link to take the whole thing, or paste several links (one per line) and they download one after another.
- Music by name. The Music tab searches YouTube, SoundCloud and Rutube at once. You get one list with covers, can listen in a built-in player, tick a few songs and download them with one button.
- Audio tracks and subtitles. Pick a language, embed subtitles or save a separate .srt.
- A browser extension (Chrome, Edge, Opera, Firefox) or a bookmarklet for everything else: open a video, click, and the app picks up the link.
- Works behind a proxy. If a site does not open directly, the app can go through your VPN app's local proxy (v2rayN, Clash, Hiddify...).
- Light and dark theme, Russian and English interface, and it keeps itself and yt-dlp up to date.
!Searching music by name
No ads, no accounts, no servers
Everything happens on your computer. The UI is just a local web page, served by a tiny Flask server that listens on 127.0.0.1 only. There is nothing to sign up for and no third-party server in the middle.
You do not need to install Python either. On first start a small script downloads a private copy of Python 3.12, yt-dlp, ffmpeg and Deno into the app folder and verifies every download with SHA-256. Nothing is installed system-wide, and the bundled uninstall script (Удалить.bat) removes it all.
Try it
1. Download universal-downloader.zip from the latest release (Windows 10/11, about 350 MB after the first-run setup).
2. Unpack it and double-click Запуск.bat ("Start").
3. A tray icon appears and the app opens in your browser.
Source code and docs: OlegChe77/universal-downloader
What I would love to hear
- Sites or links that fail for you (the error message has a "Details" button with the raw yt-dlp output, which is handy for an issue).
- What is confusing on first start.
- Missing options you would actually use.
It is a wrapper for personal use, so please download only what you have the right to, and follow the terms of the sites you use.
If you try it, tell me how it went in the comments or open an issue on GitHub.
Mentions
APIキーなしでAIコンテンツを作る設計:判断はチャットのAI、書き出しはツール AIを組み込んだツールを作ろうとすると、多くの解説で「まずAPIキーを取得しましょう」と書かれています。ツールの中からAIのAPIを呼び出す作り方です。 ただ、APIは使った分だけ料金がかかります。個人で作るツールだと、料金がいくらになるか読めないのは不安です。キーの管理にも気を使います。 この記事では、APIキーを使わずに、AIの判断を組み込んだツールを作る設計を紹介します。題材は、配信のアーカイブから切り抜き動画を作るツールです。 考え方:判断と作業を分ける 切り抜き動画を作る作業は、大きく2種類に分けられます。 種類 例 向いている担当 判断 どの場面を使うか、字幕の誤字をどう直すか、タイトルをどうするか AI 作業 文字起こし、音量の分析、動画の切り出し、字幕の焼き込み プログラム APIを使う設計では、プログラムの中からAIを呼んで、判断もまとめてやらせます。 この記事の設計では、判断は普段使っているチャットのAIに任せます。プログラムは作業だけを担当します。両者は、ファイルを通してやり取りします。 チャットのAIは、すでに払っているサブスクリプションの範囲で使えます。ツールの中にAPIの呼び出しは1つもありません。 全体の流れ 使う側から見ると、手順は3つです。 run.bat <動画のURLかファイル> を実行する(分析) チャットのAIに「〇〇の切り抜きを編集して」と頼む(判断) もう一度 run.bat <配信名> を実行する(書き出し) 1. 分析:AIが判断しやすい材料を作る 最初の実行では、プログラムが次の作業をします。 動画を取得する(yt-dlp) 文字起こしをする(faster-whisper) 音量の変化を調べる 切り抜きの候補を書き出す 取得するのは、自分の配信など、切り抜きの許可がある動画だけにします。コラボ相手が映る場合は、相手の了承も取っておきます。 候補のファイル(candidates.md)には、声が急に大きくなった場面に印を付けておきます。盛り上がった場面の目安になるからです。 分析が終わると、プログラムは止まって、次にやることを表示します。 Claudeに『配信切り抜きの〇〇を編集して』と伝えてください 2. 判断:チャットのAIが編集の指示を書く チャットのAIは、candidates.md と文字起こし(transcript.txt)を読んで、編集の指示ファイル(edit.json)を書きます。 AIが決めるのは、次のようなことです。 どの場面を使うか(離れた複数の場面をつなぐこともできる) 字幕の誤字の修正 タイトル 画面のどこに注目させるか edit.json の形は、別のファイル(EDIT_FORMAT.md)に書いておきます。AIはこのファイルを読んで、決まった形で指示を書きます。 3. 書き出し:指示どおりに動画を作る 2回目の実行では、プログラムが edit.json を読んで動画を書き出します。動画の組み立てには、Reactで動画を作れるRemotionを使っています。 一部だけ作り直したいときのオプションも用意しています。 run.bat 配信名 --only 03 05 # 3本目と5本目だけ作り直す run.bat 配信名 --analyze # 分析だけやり直す 設計のポイント 受け渡しのファイルの形を決めておく AIとプログラムの間は、ファイルでつながっています。ファイルの形がぶれると、書き出しで失敗します。 そこで、edit.json の形を文書(EDIT_FORMAT.md)にして、AIに必ず読ませます。プログラム側でも、読み込むときに形をチェックして、おかしければ分かりやすいエラーを出します。 これは、AIに使わせるCLIの記事で書いた「機械が読める出力」と同じ考え方です。今回は逆向きで、AIが書いたものをプログラムが読みます。 プログラムは「次にやること」を表示して止まる 分析が終わったところで、プログラムは次にやることを表示して止まります。 使う人は、AIとプログラムのどちらの番かを迷わずに済みます。AIにとっても、「ここから自分の番」がはっきりします。 準備は自動にする 動画のツールは、必要なものが多くなりがちです。Pythonのライブラリ、ffmpeg、フォント、BGM、Node.js、Remotionなどです。 これらは、セットアップ用のスクリプト(setup_env.py)で自動で入れるようにしています。最初の準備でつまずくと、ツールを使ってもらえないからです。 ライセンスを確かめる 動画に使う素材やライブラリは、ライセンスを確かめておきます。 フォント:Google Fontsのうち、OFL(SIL Open Font License)のもの Remotion:個人と、3人以下の会社は無料で使える(それ以外は有料のライセンスが必要) ツールごとにフォルダを分ける 同じ仕組みで、別の種類の動画を作るツールも作れます。ただ、1つのフォルダにまとめると、設定や素材が混ざってしまいます。ツールごとにフォルダを分け、それぞれにセットアップと説明書を置いています。 この設計が向いているとき・向いていないとき 向いている 向いていない 人がその場にいて、チャットで頼める 夜中に無人で、大量に処理したい 1回あたりの判断が多くない 1日に何千件も判断が必要 APIの料金やキーの管理を避けたい 判断の結果をすぐに別のシステムに渡したい 無人で大量に動かしたい場合は、APIを使う設計のほうが向いています。個人で、自分が使う分を作るなら、この設計で十分なことが多いです。 よくある失敗 受け渡しのファイルの形を決めない AIが毎回少しずつ違う形で書き、書き出しで失敗します。形を文書にして、AIに読ませましょう。 プログラムが止まらずに先へ進む AIの判断を待たずに書き出しが始まると、古い指示で動画ができてしまいます。判断が必要なところで止めて、次にやることを表示しましょう。 AIに作業までやらせる 文字起こしや動画の切り出しは、プログラムのほうが速くて確実です。AIには判断だけを任せましょう。 素材のライセンスを確かめない 公開する動画では、フォントや音楽のライセンスが問題になります。最初に確かめておきましょう。 まとめ AIをツールに組み込むのに、必ずしもAPIキーは要りません。 判断はチャットのAI、作業はプログラムに分ける 両者はファイルでやり取りし、ファイルの形は文書にしておく プログラムは、AIの番が来たら止まって知らせる AIを「ツールの部品」ではなく「一緒に作業する相手」として扱う設計です。料金を気にせず試せるので、最初の1本を作るにはちょうどいい形だと思います。 参考 Remotion Remotion License faster-whisper yt-dlp
I Built a Free, Open-Source Download Manager That Supports Torrents, Video Streams, and HTTP/3 (QUIC) Hey everyone! 👋 I've been working on a project called PIDM (Python Internet Download Manager), and I'm excited to share it with the developer community! The idea was simple: I wanted a modern download manager that could handle more than just regular HTTP downloads. Something that brings different downloading technologies together in one application, with a clean interface and no price tag. So I built PIDM. 🚀 What makes PIDM different? PIDM supports several downloading technologies and workflows: 🎬 Video and Stream Downloads with yt-dlp Powered by yt-dlp, PIDM lets you download videos and streams from supported websites without needing a separate application. 🧲 Torrent and Magnet Support Download content using both traditional .torrent files and magnet links. No need to switch to a separate torrent client for supported downloads. ⚡ HTTP/3 and QUIC Support PIDM supports modern HTTP/3 (QUIC) downloads when the remote server supports the protocol. It's exciting to bring newer web transport technology into a desktop download manager! 📦 Batch Link Processing Have multiple links to download? You can add up to 10 links at once. PIDM checks them in a batch and adds the valid downloads to your queue. Less manual work, more efficient downloading. ⌨️ Quick Link Capture Simply press Ctrl + V to quickly add a new download link. A small feature, but one that makes everyday downloading much more convenient. 🌍 Available in Multiple Languages PIDM supports multiple languages, making it accessible to users around the world. 🎨 Modern UI and Themes A modern desktop interface with multiple themes, so you can customize the appearance to your liking. 🖥️ Cross-Platform PIDM is designed to work across all major desktop platforms: - Linux - macOS - Windows 💚 Completely Free No subscriptions, no premium tiers, and no paid features. PIDM is completely free and open source. 🔗 Try PIDM GitHub repository: saeedmasoudie/PIDM If you find the project interesting, consider giving it a ⭐ on GitHub. Feedback, bug reports, feature requests, and contributions are always welcome! I'm actively interested in hearing what features you'd like to see in a modern download manager.
PythonとAIでYouTubeの音声をMIDIに自動変換する方法【Google Colab・Basic Pitch】 はじめに YouTubeで公開されている楽曲を聴いていて、その演奏をMIDIデータとして取り出せないかと考えたことがある。 MIDIデータがあれば、楽曲に含まれる音符をピアノロールで確認したり、DAWで編集したり、シンセサイザーの演奏データとして利用したりできる。 今回は、PythonとSpotifyが公開している音程推定AIのBasic Pitchを使い、YouTube動画の音声をMIDIファイルに変換するプログラムを作成する。 実行環境にはGoogle Colabを使用するため、ローカルPCにPythonの開発環境を構築する必要はない。 本記事では、以下の処理を自動化する。 YouTubeのURLを指定する yt-dlpで動画から音声を取得する FFmpegで音声をWAV形式に変換する Basic Pitchで音声全体を解析する 音程・発音開始時刻・音の長さを推定する MIDIファイルとCSVファイルを生成する Google Colabからファイルをダウンロードする ただし、音声からすべての音符を完全に復元できるわけではない。特に複数の楽器が同時に演奏される楽曲では、音程の検出漏れや誤検出が発生する。 1. 使用する技術 今回のプログラムでは、以下のライブラリとツールを使用する。 技術 役割 Python プログラム全体の制御 Google Colab Pythonの実行環境 yt-dlp YouTube動画からの音声取得 FFmpeg 音声形式の変換 Spotify Basic Pitch AIによる音程推定 TensorFlow Lite 学習済みモデルの推論 uv Python実行環境とライブラリの管理 setuptools 一部の旧ライブラリとの互換性確保 1.1 yt-dlpとは yt-dlpは、動画配信サイトなどのメディアを取得するためのオープンソースソフトウェアである。 今回のプログラムでは、YouTube動画から音声ストリームを取得するために使用する。 動画によってはWebMやM4A形式などで保存されるため、後続の解析処理に向けてFFmpegでWAV形式に変換する。 なお、YouTubeのアクセス制限などにより取得できない動画もある。利用する際は、ダウンロードと変換が許可されている音源を対象とする。 1.2 Spotify Basic Pitchとは Basic PitchはSpotifyが公開している、音声をMIDIに変換するための機械学習モデルである。 通常の音声ファイルには、時間とともに変化する音圧に対応したサンプル値が格納されている。 一方、MIDIは音声の波形そのものではなく、音符に関する情報を記録する。 主な情報は以下のとおりである。 MIDIノート番号 音符の発音開始時刻 音符の終了時刻 ベロシティ ピッチベンド Basic Pitchは音声信号を解析し、こうした情報を推定する。 複数の音程が同時に鳴る場合にも対応しているが、特に単一楽器の録音を対象とした音程推定に適している。 1.3 TensorFlow Liteとは TensorFlow Liteは、学習済みの機械学習モデルを比較的軽量な実行環境で推論するための仕組みである。 Basic PitchにはTensorFlow、TensorFlow Lite、ONNXなど複数のモデル形式が用意されている。 今回はGoogle ColabのPython環境との互換性を考慮し、Python 3.10とTensorFlow Liteを組み合わせる。 2. 音声からMIDIを生成する仕組み ここでは、音声信号を音符データに変換する基本的な考え方を説明する。 2.1 音声信号を数値として扱う デジタル音声は、一定の時間間隔で音声信号を標本化したデータである。 例えば、サンプリング周波数が22,050 Hzの場合、1秒間に22,050個のサンプルを記録する。 離散時間の音声信号を次のように表す。 x[n] = x\left(\frac{n}{f_s}\right) ここで、 x[n] は離散時間信号 n はサンプル番号 f_s はサンプリング周波数 である。 音声の音程を解析するには、この時間領域の信号に含まれる周期的な特徴を調べる必要がある。 2.2 短時間フーリエ変換 音声の周波数成分を時間ごとに調べる代表的な手法が、短時間フーリエ変換(STFT)である。 X(m,k)= \sum_{n=0}^{N-1} x[n+mH]w[n] e^{-j2\pi kn/N} 各記号は以下を表す。 x[n] は音声サンプル w[n] は窓関数 N はFFTの窓長 H はホップ長 m は時間フレーム k は周波数ビン STFTによって、音声に含まれる周波数成分の時間変化を調べられる。 ただし、フーリエ変換によって得られた周波数成分を、そのままMIDIノートに変換できるわけではない。 実際の楽器音には基本周波数に加えて倍音が含まれ、複数の楽器音が重なる場合もある。 そのため、音程推定には複数の周波数成分の関係や、時間方向の特徴を考慮する必要がある。 なお、Basic Pitchの内部処理は単純なSTFTのピーク検出だけで構成されているわけではなく、学習済みニューラルネットワークを使用している。 2.3 周波数とMIDIノート番号 平均律では、音の周波数とMIDIノート番号の間に次の関係がある。 f=440\times 2^{\frac{n-69}{12}} ここで、 f は周波数(Hz) n はMIDIノート番号 440 HzはA4の基準周波数 である。 この式を変形すると、 n=69+12\log_2\left(\frac{f}{440}\right) となる。 例えば、440 Hzの音に対応するMIDIノート番号は69である。 音名 周波数の目安 MIDIノート番号 C4 261.63 Hz 60 D4 293.66 Hz 62 E4 329.63 Hz 64 A4 440.00 Hz 69 C5 523.25 Hz 72 ただし、音声からMIDIを生成する場合には音高だけでは不十分である。 音符がいつ始まったのか、いつ終わったのかも推定しなければならない。 2.4 AIによる音符イベントの推定 Basic Pitchは音声から、音の立ち上がり、継続状態、ピッチ変化などを推定する。 これらの情報を利用して、音符イベントを生成する。 例えば、次のような音符情報が得られたとする。 開始時刻 終了時刻 音高 0.00秒 0.50秒 C4 0.50秒 1.00秒 E4 1.00秒 1.50秒 G4 これらをMIDIファイルに保存すれば、DAWなどでピアノロールとして表示できる。 3. Google Colabでプログラムを実行する 実行環境はGoogle Colabを使用する。 colab.research.google.com 新しいノートブックを作成し、次のコードを1つのコードセルに貼り付ける。 冒頭の YOUTUBE_URL に変換したいYouTube動画のリンクを指定する。 以下では、実装例としてYouTubeのURLを設定済みにしている。 4. Pythonプログラム全文 ============================================================ YouTube to MIDI Converter Google Colab用 # YouTubeの音声をAIで解析してMIDIに変換する # 使用ライブラリ yt-dlp FFmpeg Spotify Basic Pitch TensorFlow Lite # 出力 MIDIファイル (.mid) 音符情報 (.csv) ============================================================ ============================================================ 0. YouTubeのリンクを設定 ============================================================ YOUTUBE_URL = "youtu.be" 別の動画に変更する場合はURLを書き換える ============================================================ 1. 必要なライブラリを準備 ============================================================ import os import sys import subprocess import tempfile from pathlib import Path from google.colab import files def run_command(command): """コマンドを実行し、実行結果を表示する""" result = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) print(result.stdout) if result.returncode != 0: raise RuntimeError( f"コマンド実行失敗: {result.returncode}" ) return result print("ライブラリをインストール中...") run_command([ sys.executable, "-m", "pip", "install", "-q", "-U", "yt-dlp[default]", "uv" ]) ============================================================ 2. Denoを準備 ============================================================ print("YouTube音声取得環境を準備中...") DENO_PATH = ( Path.home() / ".deno" / "bin" / "deno" ) if not DENO_PATH.exists(): run_command([ "bash", "-c", "curl -fsSL deno.land | sh" ]) os.environ["PATH"] = ( str(DENO_PATH.parent) - os.pathsep - os.environ["PATH"] ) print("Deno準備完了") ============================================================ 3. URLの確認 ============================================================ if not YOUTUBE_URL.startswith(( "youtube.com", "youtube.com", "youtu.be", "music.youtube.com" )): raise ValueError( "YouTubeのURLを確認してください" ) ============================================================ 4. 作業フォルダを作成 ============================================================ WORK_DIR = Path( tempfile.mkdtemp( prefix="youtube_midi_", dir="/content" ) ) OUTPUT_DIR = WORK_DIR / "output" OUTPUT_DIR.mkdir( parents=True, exist_ok=True ) print("作業フォルダ:", WORK_DIR) ============================================================ 5. YouTubeから音声を取得 ============================================================ print("YouTubeから音声を取得中...") run_command([ sys.executable, "-m", "yt_dlp", "--no-playlist", "-f", "bestaudio/best", "-o", str(WORK_DIR / "source.%(ext)s"), YOUTUBE_URL ]) ============================================================ 6. ダウンロードした音声を確認 ============================================================ audio_files = [ p for p in WORK_DIR.glob("source.*") if p.is_file() and p.suffix not in ( ".part", ".ytdl" ) ] if not audio_files: raise RuntimeError( "YouTube音声の取得に失敗しました" ) AUDIO_PATH = audio_files[0] print("音声取得完了") print("ファイル:", AUDIO_PATH.name) ============================================================ 7. 音声をWAV形式に変換 ============================================================ print("WAV形式に変換中...") WAV_PATH = WORK_DIR / "audio.wav" run_command([ "ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", str(AUDIO_PATH), "-vn", "-ac", "1", "-ar", "22050", "-c:a", "pcm_s16le", str(WAV_PATH) ]) if not WAV_PATH.exists(): raise RuntimeError( "WAVファイルが生成されませんでした" ) print("WAV変換完了") ============================================================ 8. Basic Pitchの実行環境を設定 ============================================================ print("AI音程推定環境を準備中...") Python 3.10を使用 setuptoolsを固定してpkg_resourcesエラーを対策 TensorFlow Lite版を使用 BASIC_PITCH_COMMAND = [ "uv", "run", "--no-project", "--python", "3.10", "--with", "setuptools==80.9.0", "--with", "basic-pitch==0.4.0", "--with", "tflite-runtime==2.14.0", "--with", "numpy<2", "--", "basic-pitch", str(OUTPUT_DIR), str(WAV_PATH), "--model-serialization", "tflite", "--save-note-events" ] ============================================================ 9. AIで音声全体を解析 ============================================================ print("================================") print("AIで音声全体を解析中...") print("================================") result = subprocess.run( BASIC_PITCH_COMMAND, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) print(result.stdout) if result.returncode != 0: raise RuntimeError( "Basic PitchによるMIDI変換に失敗しました。" "上の実行ログを確認してください。" ) print("AI音程解析完了") ============================================================ 10. MIDIファイルを確認 ============================================================ midi_files = sorted( OUTPUT_DIR.glob("*.mid") ) if not midi_files: raise RuntimeError( "MIDIファイルが生成されませんでした" ) print("MIDI変換成功") for midi in midi_files: print( "MIDIファイル:", midi.name ) ============================================================ 11. MIDIファイルをダウンロード ============================================================ print("MIDIファイルをダウンロード中...") for midi in midi_files: files.download( str(midi) ) ============================================================ 12. CSV形式の音符情報もダウンロード ============================================================ csv_files = sorted( OUTPUT_DIR.glob("*.csv") ) for csv_file in csv_files: files.download( str(csv_file) ) ============================================================ 13. 完了 ============================================================ print("================================") print("YouTube to MIDI 変換完了") print("================================") print("保存先:", OUTPUT_DIR) print("生成されたMIDI:") for midi in midi_files: print(midi.name) print("すべての処理が終了しました") このコードはGoogle Colab上での動作を想定しているが、全処理の実行検証は完了していない。PythonパッケージやYouTubeの仕様変更によって修正が必要になる可能性がある。 5. プログラムの解説 5.1 YouTubeのURLを設定する プログラム冒頭の次の部分で、変換対象の動画を指定する。 YOUTUBE_URL = "youtu.be" URLはPythonの文字列として指定する必要がある。 Markdownのリンク記法をそのままPythonコードに貼り付けると、SyntaxErrorが発生するので注意する。 5.2 yt-dlpで音声を取得する run_command([ sys.executable, "-m", "yt_dlp", "--no-playlist", "-f", "bestaudio/best", "-o", str(WORK_DIR / "source.%(ext)s"), YOUTUBE_URL ]) この部分では、yt-dlpを使ってYouTube動画の音声を取得している。 --no-playlist はプレイリスト全体をダウンロードしないための指定である。 -f bestaudio/best は音声を優先して取得するための指定である。 また、ファイル名の拡張子は取得したフォーマットによって決まる。 例えば、WebM形式の音声が取得された場合は、source.webmというファイルが生成される。 5.3 FFmpegでWAV形式に変換する run_command([ "ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-i", str(AUDIO_PATH), "-vn", "-ac", "1", "-ar", "22050", "-c:a", "pcm_s16le", str(WAV_PATH) ]) この処理では、取得した音声をWAV形式に変換する。 各オプションの意味は以下のとおりである。 オプション 意味 -i 入力ファイルの指定 -vn 動画ストリームを除外 -ac 1 モノラル音声へ変換 -ar 22050 サンプリング周波数22,050 Hz -c:a pcm_s16le 16ビット符号付きPCMで保存 -y 既存ファイルを上書き ここでサンプリング周波数を22,050 Hzにしているが、これだけで音程推定が完成するわけではない。 次のBasic Pitchによる推論処理が必要になる。 なお、Basic Pitch側では必要に応じて音声の再サンプリングなどが行われる。 5.4 Basic Pitchを実行する MIDI変換の中心となるのが、次の部分である。 BASIC_PITCH_COMMAND = [ "uv", "run", "--no-project", "--python", "3.10", "--with", "setuptools==80.9.0", "--with", "basic-pitch==0.4.0", "--with", "tflite-runtime==2.14.0", "--with", "numpy<2", "--", "basic-pitch", str(OUTPUT_DIR), str(WAV_PATH), "--model-serialization", "tflite", "--save-note-events" ] Google Colabの標準Python環境とBasic Pitchの対応バージョンが一致しない場合がある。 そのため、uvを使ってPython 3.10の独立した実行環境を用意している。 --model-serialization tflite は、TensorFlow Lite形式のモデルを使用するための指定である。 --save-note-events を指定すると、MIDIに加えて推定した音符イベントをCSV形式でも出力できる。 5.5 MIDIファイルをダウンロードする midi_files = sorted( OUTPUT_DIR.glob("*.mid") ) for midi in midi_files: files.download(str(midi)) Basic Pitchが生成したMIDIファイルを取得し、Google Colabのダウンロード機能で保存している。 生成されたファイルは、MIDI対応のDAWやピアノロール表示ソフトで読み込める。 6. 実行時に発生したエラーと対策 今回の実装では、Python環境とライブラリの互換性について注意が必要だった。 6.1 Pythonのバージョン問題 Google ColabのPythonバージョンは更新されることがある。 一方、今回使用するBasic Pitch 0.4.0は、Python 3.10や3.11を含む環境を対象としている。 対応していないPythonバージョンに直接インストールすると、依存ライブラリの解決で失敗する可能性がある。 この問題に対して、今回のコードでは次の指定を使用している。 "uv", "run", "--no-project", "--python", "3.10", ColabのPython自体を変更せず、Basic Pitchだけを別のPython環境で実行する方法である。 6.2 pkg_resourcesが見つからない問題 実装中、次のエラーが発生した。 ModuleNotFoundError: No module named 'pkg_resources' これは、Basic Pitchが依存するresampyがpkg_resourcesを読み込もうとした際に発生したエラーである。 pkg_resourcesは従来setuptoolsに含まれていたが、新しいsetuptoolsでは削除されている。 そこで、今回のコードでは次のようにバージョンを固定した。 "--with", "setuptools==80.9.0", この指定は旧APIとの互換性を確保するための対策である。将来的にはライブラリ側の更新に合わせた対応が望ましい。 6.3 TensorFlow関連の警告 実行時に次のような警告が表示されることがある。 Tensorflow is not installed. Coremltools is not installed. onnxruntime is not installed. Basic Pitchが複数の推論エンジンに対応していることに関連する警告である。 今回のプログラムではTensorFlow Liteを明示的に使用しているため、これらの警告だけで必ずしも変換失敗を意味するわけではない。 ただし、TensorFlow Lite側のモデル読み込みに失敗している場合は、別途エラー内容の確認が必要である。 6.4 YouTubeの音声を取得できない場合 yt-dlpを使用していても、すべての動画を取得できるとは限らない。 例えば、動画のアクセス制限、YouTube側の仕様変更、Colabからのアクセス制限などが原因となることがある。 この場合は、yt-dlpの実行ログを確認する。 今回のコードではDenoをインストールし、YouTubeのJavaScript処理に対応する構成としているが、取得成功を保証するものではない。 7. 変換精度の限界 音声からMIDIへの変換は、音響信号から音符を推定する問題である。 そのため、元のMIDIファイルを完全に復元する処理とは異なる。 7.1 単一楽器の演奏 ピアノやギターなどの単一楽器を録音した音源では、音程の推定が比較的行いやすい。 特に、録音状態が良く、音符の立ち上がりが明確な場合は解析しやすくなる。 7.2 複数の楽器による演奏 バンド演奏では、ギター、ベース、ドラム、ボーカルなどが同時に鳴る。 この場合、各楽器の周波数成分が重なり、音程の推定が難しくなる。 例えば、エレキギターの倍音が別の音符として誤認識されることがある。 また、ドラムのような非調波的な音は、通常の音高を持つ楽器とは性質が異なるため、Basic Pitchだけで正確なドラムMIDIを生成することは難しい。 7.3 MIDIは元の音色を保存しない MIDIファイルには、元の音声波形がそのまま保存されるわけではない。 そのため、エレキギターの音声をMIDIに変換しても、ディストーションの音色やアンプの特性まで再現されるわけではない。 MIDIから音を再生するには、別途シンセサイザーや音源が必要になる。 8. 今後の拡張 今回のプログラムは、YouTubeの音声を一括してMIDIに変換する構成である。 さらに精度を高めたい場合は、音源分離技術を組み合わせる方法が考えられる。 例えば、Demucsなどの音源分離モデルを使って楽曲をボーカル、ドラム、ベース、その他の成分に分離し、その後で音程推定を行う方法である。 音源分離そのものにも誤差はあるが、混合音源をそのまま解析する場合とは異なるアプローチが可能になる。 また、次のような拡張も考えられる。 楽器別MIDIファイルの生成 MIDIのピアノロール可視化 ノートイベントの重複除去 BPM推定と音符のクオンタイズ MIDIノート番号と周波数の比較 FFT・スペクトログラム・MIDIの同時可視化 特に、音声のスペクトログラムとMIDIのピアノロールを比較できれば、デジタル信号処理の学習教材としても利用できる。 9. まとめ 今回は、PythonとSpotify Basic Pitchを使い、YouTube動画の音声全体をMIDIデータに変換するプログラムを実装した。 プログラムでは、yt-dlpによる音声取得、FFmpegによるWAV変換、Basic Pitchによる音程推定、MIDIとCSVの出力を組み合わせている。 また、Google ColabのPython環境との互換性を考慮し、uvを使ってPython 3.10の実行環境を用意した。 音声をMIDIに変換する技術は、単なる楽曲の採譜だけでなく、音響信号処理、機械学習、デジタルシンセサイザー、音楽情報検索などとも関係している。 今回のプログラムは、その仕組みを実際の音源を使って学ぶための出発点になる。 なお、コードはColabでの一連の動作確認が完了していないため、実際の利用時には生成結果と実行ログを確認する必要がある。 参考資料 Spotify Basic Pitch - GitHub Basic Pitch - PyPI yt-dlp - GitHub FFmpeg Documentation Google Colab uv Documentation TensorFlow Lite
How does this compare to yt-dlp/yt-dlp ?
@TeamHFC مستحيل .. شيك هنا او عط كلود وهو يتصرف yt-dlp/yt-dlp
It's getting much more difficult to run. YouTube often requires PO tokens [1] to download videos now. [1]: github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide
长视频变笔记,拆成取音频、转文字、提要点。 yt-dlp:从支持的网站下载音视频,适合整理获授权的课程、访谈素材。 起步:用 yt-dlp -x "视频链接" 提取音频。 门槛:需命令行;该功能依赖 ffmpeg/ffprobe。 文档核验,未实测。 yt-dlp/yt-dlp
This is the same reason yt-dlp recommends avoiding self-update for their patch for this: github.com/yt-dlp/yt-dlp/releases/tag/2026.10.21
I built a free YouTube/SoundCloud downloader for Windows that runs entirely on your PC Every "download a YouTube video" website looks the same: ads, pop-ups, and a big green button that takes you somewhere you did not want to go. And if you need a different site (SoundCloud, Vimeo, TikTok...), you need a different downloader. I wanted one place where I could drop any link and get a normal file. So I built Universal Downloader, a free, open-source Windows app on top of yt-dlp. !Pasting a link and picking a quality What it does - Paste a link, get a file. YouTube, SoundCloud, Vimeo, TikTok, Instagram and 1000+ other sites that yt-dlp supports. MP4 from 144p to 4K, MP3 with cover art and tags, or M4A without re-encoding. - Playlists and queues. Paste a playlist link to take the whole thing, or paste several links (one per line) and they download one after another. - Music by name. The Music tab searches YouTube, SoundCloud and Rutube at once. You get one list with covers, can listen in a built-in player, tick a few songs and download them with one button. - Audio tracks and subtitles. Pick a language, embed subtitles or save a separate .srt. - A browser extension (Chrome, Edge, Opera, Firefox) or a bookmarklet for everything else: open a video, click, and the app picks up the link. - Works behind a proxy. If a site does not open directly, the app can go through your VPN app's local proxy (v2rayN, Clash, Hiddify...). - Light and dark theme, Russian and English interface, and it keeps itself and yt-dlp up to date. !Searching music by name No ads, no accounts, no servers Everything happens on your computer. The UI is just a local web page, served by a tiny Flask server that listens on 127.0.0.1 only. There is nothing to sign up for and no third-party server in the middle. You do not need to install Python either. On first start a small script downloads a private copy of Python 3.12, yt-dlp, ffmpeg and Deno into the app folder and verifies every download with SHA-256. Nothing is installed system-wide, and the bundled uninstall script (Удалить.bat) removes it all. Try it 1. Download universal-downloader.zip from the latest release (Windows 10/11, about 350 MB after the first-run setup). 2. Unpack it and double-click Запуск.bat ("Start"). 3. A tray icon appears and the app opens in your browser. Source code and docs: OlegChe77/universal-downloader What I would love to hear - Sites or links that fail for you (the error message has a "Details" button with the raw yt-dlp output, which is handy for an issue). - What is confusing on first start. - Missing options you would actually use. It is a wrapper for personal use, so please download only what you have the right to, and follow the terms of the sites you use. If you try it, tell me how it went in the comments or open an issue on GitHub.
Rustdesk: Open-source remote desktop application; Neovim; Ente | GitHub Curated Picks | 2026-10-27 Chapters: 00:00 2026-10-27 | GitHub Curated Picks 00:05 Pick #1 Rustdesk 00:17 Pick #2 Neovim 00:34 Pick #3 Jellyfin 00:38 Pick #4 Ente 00:41 Pick #5 yt-dlp GitHub Curated Picks reviews 5 source-verified repositories selected for developer usefulness, not popularity position. Each pick is checked against its GitHub repository, README, release evidence, and recent commit; pick numbers are editorial order. The compact card keeps rank, signal, why it matters, and next check together while the ledger preserves direct URLs and release evidence. Treat the list as an educational review surface, not software endorsement, and verify license and maintenance before adoption. Published: 2026-10-27 Review window: daily Curated repository picks: - Pick #1 Rustdesk | Latest commit | fix(windows): name the privacy window executable explicitly (reference | rustdesk/rustdesk - Pick #2 Neovim | Latest commit | build(deps): bump tree-sitter-markdown to v0.5.4 (reference 42520) | neovim/neovim - Pick #3 Jellyfin | 12.4 | Translated using Weblate (Lithuanian) Translation: Jellyfin/Jellyfin | jellyfin/jellyfin - Pick #4 Ente | locker-v1.0.11 | [rust] Align two-factor recovery encoding (reference 14105) Match | ente/ente - Pick #5 yt-dlp | yt-dlp 2026.10.26 | Release 2026.10.26 Created by: bashonly :ci skip all | yt-dlp/yt-dlp Chapters: 00:00 2026-10-27 | GitHub Curated Picks 00:05 Pick #1 Rustdesk 00:17 Pick #2 Neovim 00:34 jellyfin/jellyfin 00:38 ente/ente 00:41 yt-dlp/yt-dlp 00:43 Watch Next 00:51 Educational Use Only Top comment prompt: Which repository would you verify first, and what release or commit evidence matters most? Source ledger: Direct source URLs: - github.com/trending - api.github.com - github.com/rustdesk/rustdesk/blob/master/README.md - github.com/rustdesk/rustdesk/releases/tag/1.5.0 - github.com/rustdesk/rustdesk/commit/59f2953c94b83… - rustdesk/rustdesk - api.github.com - github.com/neovim/neovim/blob/master/README.md - github.com/neovim/neovim/releases/tag/v0.12.6 - github.com/neovim/neovim/commit/3ee26cf91f28cfac9… - neovim/neovim - api.github.com - github.com/jellyfin/jellyfin/blob/master/README.md - github.com/jellyfin/jellyfin/releases/tag/v12.4 - github.com/jellyfin/jellyfin/commit/02c2951eb72d7… - jellyfin/jellyfin - api.github.com - github.com/ente/ente/blob/main/README.md - github.com/ente/ente/releases/tag/locker-v1.0.11 - github.com/ente/ente/commit/ee869b1195a69488b7568… - ente/ente - api.github.com - github.com/yt-dlp/yt-dlp/blob/master/README.md - github.com/yt-dlp/yt-dlp/releases/tag/2026.10.26 - github.com/yt-dlp/yt-dlp/commit/f264a6cbd1f630894… - yt-dlp/yt-dlp Informational and educational purposes only. Not investment advice, product endorsement, or professional guidance. Subscriber reason: Subscribe for the daily AI, GitHub, and market board. Tomorrow watchlist: Tomorrow, check the next tagged release, recent commit, and issue-health signals for the selected projects.