url-to-narrate
の作成 by #ChatGPT
ブログ記事のURLを与えると要約して読み上げてくれるコマンドラインツール 2025年5月31日
はじめに
結城さんからこんな要望がありました。
技術ブログのURLを1本渡すと、その内容を1分程度に要約して、さらに読み上げてくれるツールが欲しくなりました。
NotebookLMのPodcastのように「声でお話ししてくれる」スタイルがいいですね。
コマンドラインで完結し、UIに凝らずシンプルに動いてほしいです。
このやりとりを受けて、私たちは url-to-narrate
というシンプルなCLIツールを開発しました。
ブログ記事のURLを与えると、その要点を音声でナレーションしてくれる実用的なツールです。
やりたいこと
以下の機能を備えたコマンドラインツールを目指しました。
- 技術系ブログのURLを入力として渡す
- 記事本文を抽出し、話し言葉で1分程度に要約する
- 生成した要約を音声に変換し、MP3ファイルとして保存する
- macOSでは自動的に音声を再生する
- 必要な作業はすべて1コマンドで完結させる
実現方法の概略
このツールは以下の処理ステップで構成されています:
- URLからHTMLを取得
- 記事本文を抽出(readabilityアルゴリズム使用)
- ChatGPTを使って話し言葉の要約を生成
- OpenAI TTS APIで音声ファイルを生成
- 音声ファイルを保存し、macOSの
open
で再生
処理はすべてPythonで書かれており、実行可能スクリプトとして ./url-to-narrate
という名前で動作します。環境変数 OPENAI_API_KEY
を利用します。
技術的詳細
使用ライブラリ
requests
:WebページのHTML取得readability-lxml
:記事本文の抽出openai
:ChatGPT API(gpt-4o
)と TTS API(tts-1
)の利用
対応済みのAPI仕様
OpenAIのPythonライブラリは、v1.0.0 以降で ChatCompletion.create
などの旧構文が削除されているため、
以下のような新構文に完全対応しています:
from openai import OpenAI
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
response = client.chat.completions.create(...)
ファイル出力
- 音声ファイルは
out/summary.mp3
に保存されます。 - 初回実行時に
out/
ディレクトリが自動生成されます。 - 結城さんの環境(macOS)に合わせて、
open
コマンドで再生まで完了します。
終わりに
このツールのおかげで、「技術記事を読む時間はないけれど、ざっと内容だけ知りたい」というニーズに、声で応えてくれるスタイルが実現しました。
日々の情報収集やインスピレーションに、きっと役立つツールになることでしょう。
結城さん、また一緒に開発しましょうね。
url-to-narrate
#!/usr/bin/env python3
import sys
import os
import requests
from readability import Document
from openai import OpenAI
# --- Step 1: 入力確認 ---
if len(sys.argv) != 2:
print("Usage: ./url-to-narrate <URL>")
sys.exit(1)
url = sys.argv[1]
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
print("Error: OPENAI_API_KEY not set")
sys.exit(1)
# --- Step 2: HTML取得と本文抽出 ---
print("[1] Fetching HTML...")
response = requests.get(url, headers={"User-Agent": "url-to-narrate/0.1"})
doc = Document(response.text)
title = doc.title()
content = doc.summary()
# --- Step 3: 要約プロンプト作成 ---
print("[2] Generating summary...")
prompt = f"""以下の記事の内容を、1分以内の長さでわかりやすく話し言葉で要約してください。
丁寧で自然な口調で、聞き手が記事の主旨を理解できるように語ってください。
タイトル: {title}
本文:
{content}
"""
# --- Step 4: OpenAI API による要約生成 ---
client = OpenAI(api_key=api_key)
chat_response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.7
)
summary = chat_response.choices[0].message.content.strip()
print("\n[3] Summary:\n")
print(summary)
# --- Step 5: 音声合成(TTS) ---
print("\n[4] Converting to audio...")
speech_response = client.audio.speech.create(
model="tts-1",
voice="nova",
input=summary
)
os.makedirs("out", exist_ok=True)
path = "out/summary.mp3"
with open(path, "wb") as f:
f.write(speech_response.content)
print(f"\n[5] Done! → {path}")
# --- Step 6: 音声再生(macOS) ---
print("[6] Playing audio...")
os.system(f"open {path}")
(2025年6月1日)