Skip to content

Repository files navigation

📻 AirWave · 终端网络电台

零依赖 · 跨平台 · 可脚本化的终端互联网电台播放器 / Zero-dependency terminal internet radio

Python License: MIT Runtime Deps Tests

🌐 语言 / Language:简体中文 | 繁體中文English


🎉 项目介绍

AirWave 是一款运行在终端里的互联网电台播放器:不需要图形界面、不需要任何第三方运行时库,只用 Python 标准库就能收听全球数万个网络电台,实时看到 Now-Playing 曲目信息,并能把直播流原样录制下来。

它解决了这些真实痛点:

  • 🥱 图形播放器太重:浏览器标签页 + 网页播放器占用大量内存,而你只想边写代码边听点背景音。
  • 🧩 流格式五花八门:电台地址可能是 M3U、PLS、XSPF、ASX,甚至多层嵌套;Shoutcast/Icecast 的元数据还被穿插在音频字节流里,普通播放器经常读不到歌名。
  • 🛰️ 网络环境不稳定:电台目录服务偶尔抽风、公网不可达时播放器直接“白板”。
  • 🖥️ 服务器/无头环境无解:没有声卡的机器上,绝大多数播放器无法启动,更别说定时录制节目。

🌟 自研差异化亮点

能力 说明
零三方依赖 运行时只使用 Python 3.8+ 标准库,pip install 后无传递依赖、无供应链负担
双目录容灾 在线对接 Radio Browser(约 5 万家电台,多节点故障转移),失败自动回退到内置 27 个精选台,完全离线可用
全格式解析 M3U / M3U8 / PLS / XSPF / ASX 全覆盖,支持嵌套播放列表解析、相对路径补全、循环引用保护
ICY 解复用 纯手写 icy-metaint 状态机,精确分离音频字节与 StreamTitle 元数据,录制文件不含元数据帧
可插拔后端 mpv / ffplay / VLC / MPlayer 自动探测;独创 null 无头后端,让服务器与 CI 也能跑通“解析→录制→统计”全链路
双界面 可脚本化 CLI(支持 JSON 事件流)+ curses 全屏 TUI,同一套播放引擎
工程完备 67 个单元/集成测试、本地模拟 Shoutcast 服务器、TUI 伪终端冒烟、wheel/sdist 打包校验

💡 灵感来源:GitHub Trending 上的终端音频播放器热潮(如 bjarnee/cliamp,周增近 4000 Star)证明了“终端收听”的真实需求。AirWave 没有复制任何现有项目的代码,而是独立设计了一条网络电台优先、零依赖、无头可测的技术路线,并在目录容灾、播放列表格式、ICY 解析与可脚本化方向做了差异化增强。


✨ 核心特性

  • 📻 海量电台目录:名称 / 标签 / 国家代码多维搜索,热门榜单一键获取,无需 API Key
  • 📶 离线精选目录:内置 SomaFM、Radio Paradise、KEXP、FIP、Radio Swiss 等 27 个稳定公开流,断网也能浏览
  • 🎶 实时 Now-Playing:自动解复用 ICY 元数据,终端里实时滚动当前曲目
  • 📄 五种播放列表格式M3U / M3U8 / PLS / XSPF / ASX,自动识别格式、自动嵌套跳转
  • ⏺️ 边听边录 / 纯录制:支持定时停止、定量停止、安全文件名,录制结果是纯净音频流(自动剔除 ICY 帧)
  • 🔌 后端自动探测:按 mpv → ffplay → mplayer → vlc → null 优先级选择,也可 --backend 手动指定
  • 收藏与历史:本地 JSON 原子写入,收藏增删查、收听历史、JSON/CSV 导出
  • 💻 curses 全屏 TUI:榜单 / 收藏 / 内置目录三个数据源、关键词搜索、一键收藏、一键录制
  • 🧑‍💻 JSON 事件流--json 输出结构化播放事件,方便接入脚本、状态栏、通知系统
  • 🪶 跨平台:Linux / macOS 原生可用;Windows 通过可选的 windows-curses 使用 TUI,CLI 全平台一致
  • 🔒 隐私友好:无账号、无遥测、无埋点;收藏与历史只保存在本机配置目录

🚀 快速开始

🧰 环境要求

项目 要求
Python 3.8 及以上(3.8 / 3.9 / 3.10 / 3.11 / 3.12 均已兼容)
运行时依赖 (仅标准库)
播放后端(可选) 系统中安装任意一个即可:mpv、ffmpeg 自带的 ffplay、VLC、MPlayer;都没有时可用 null 后端跑录制与解析
网络 在线目录/收听需要联网;内置目录与本地播放列表离线可用

📦 安装

# 方式一:pip 安装(推荐)
pip install airwave-radio

# Windows 用户如需 TUI,补装可选依赖:
pip install "airwave-radio[windows]"

# 方式二:pipx 隔离安装(命令行工具首选)
pipx install airwave-radio

# 方式三:源码运行(零安装)
git clone https://github.com/gitstq/airwave.git
cd airwave
PYTHONPATH=src python3 -m airwave --version

🎧 30 秒上手

# 1. 看看本机有哪些可用播放后端
airwave backends

# 2. 浏览热门电台(在线 Radio Browser,自动回退内置目录)
airwave top --limit 15

# 3. 搜索关键词
airwave search "jazz"
airwave search "" --tag ambient --country US

# 4. 直接播放:支持「电台名 / 收藏名 / 直接 URL」三种写法
airwave play "Groove Salad"
airwave play https://ice1.somafm.com/groovesalad-128-mp3

# 5. 全屏终端界面
airwave tui

🎧 没有安装任何播放器?先 airwave play "Groove Salad" --backend null 验证链路,再按 后端安装指引 装一个 ffplay/mpv。


📖 详细使用指南

全部命令一览

命令 作用
airwave top 热门电台榜单
airwave search <关键词> 按名称/标签/国家搜索
airwave play <目标> 播放(目标 = 名称、收藏名或 URL)
airwave record <目标> 无界面录制(自动使用 null 后端)
airwave fav add/list/rm 收藏管理
airwave history 收听历史 / 导出 / 清空
airwave catalog 浏览内置离线目录
airwave backends 探测播放后端
airwave tui 全屏终端界面

📻 发现电台

# 在线热门榜(默认 30 条)
airwave top --limit 20

# 只看内置离线目录(飞机上/内网环境)
airwave top --offline
airwave catalog --tags            # 列出内置目录全部标签
airwave catalog --tag jazz        # 按标签筛内置目录

# 多条件搜索
airwave search paradise
airwave search "" --tag classical --country CH --limit 10

# 给脚本用:输出 JSON
airwave search soma --json

▶️ 播放与实时曲目

# 名称会按「收藏 → 在线/离线目录」顺序自动匹配
airwave play "Radio Paradise"

# 直接给流地址或播放列表地址(.m3u/.pls/.xspf/.asx 会自动解析嵌套)
airwave play https://example.com/station.m3u

# 指定后端 / 音量 / 播放 10 分钟后自动退出
airwave play "Drone Zone" --backend ffplay --volume 80 --duration 600

# 结构化事件流(适合写脚本、接入 polybar/tmux 状态栏)
airwave play "Groove Salad" --backend null --json
# 输出示例:
# {"event":"connected","content_type":"audio/mpeg","bitrate":128,...}
# {"event":"metadata","title":"Rena Jones - Driftwood"}
# {"event":"status","elapsed":8.9,"kbps":128.2,...}
# {"event":"ended",...}

⏺️ 录制电台

# 边听边录(录满 30 分钟自动停止)
airwave play "Groove Salad" --record --record-for 1800

# 无界面纯录制(服务器定时任务场景,不依赖声卡)
airwave record "FIP" --duration 3600
airwave record https://ice1.somafm.com/dronezone-128-mp3 --out ~/show.mp3 --duration 1800

# 配合系统定时任务,每天凌晨录一档节目
# crontab 示例:
0 1 * * * /usr/bin/airwave record "FIP" --duration 3600

录制文件默认保存在:

  • Linux:~/.local/share/airwave/recordings/
  • macOS:~/Library/Caches/airwave/recordings/
  • Windows:%LOCALAPPDATA%\airwave\recordings\
  • 可用环境变量 AIRWAVE_RECORDINGS 覆盖目录。

⭐ 收藏与收听历史

airwave fav add "我的台" https://example.com/stream --tags "jazz,lofi"
airwave fav list
airwave fav rm "我的台"

airwave history                 # 最近 20 条
airwave history --export h.csv  # 导出 CSV(也支持 .json)
airwave history --clear         # 清空

收藏/历史文件位于配置目录(Linux/macOS:~/.config/airwave/,Windows:%APPDATA%\airwave\),写入采用临时文件 + 原子替换,进程崩溃也不会损坏资料库。

💻 TUI 按键说明

启动:airwave tui(追加 --offline 仅用内置目录,--backend ffplay 指定后端)

按键 功能
/ j k 移动光标,PgUp/PgDn 翻页
Enter 播放选中电台
x 停止播放
r 边听边录
f 收藏 / 取消收藏
/ 输入关键词搜索(Enter 确认,Esc 取消)
1 / 2 / 3 切换 热门榜 / 收藏 / 内置目录
q 退出

🖼️ 演示动图/截图占位:docs/demo/(欢迎 PR 补充你的运行截图)

🔧 环境变量

变量 作用 默认
AIRWAVE_BACKEND 默认播放后端(等价 --backend 自动探测
AIRWAVE_RECORDINGS 录制输出目录 系统数据目录
XDG_CONFIG_HOME / XDG_DATA_HOME Linux 配置/数据根目录 遵循 XDG 规范
APPDATA / LOCALAPPDATA Windows 配置/数据目录 系统默认

🔌 播放后端安装对照

后端 安装(Linux) 安装(macOS) 安装(Windows) 喂流方式
mpv(推荐) apt install mpv brew install mpv 官网下载加入 PATH 管道喂流
ffplay apt install ffmpeg brew install ffmpeg 下载 ffmpeg 管道喂流
VLC apt install vlc brew install --cask vlc 官网安装 后端直连 URL
MPlayer apt install mplayer brew install mplayer 构建安装 管道喂流
null(内置) 无需安装 无需安装 无需安装 丢弃音频,仅跑链路

❓ 常见问题(FAQ)

Q1:提示“未找到任何可用播放后端”? A:AirWave 自身不发声,需要系统里有 mpv/ffplay/VLC/MPlayer 之一;临时验证可用 --backend null,服务器录制场景也用它。

Q2:TUI 启动报 curses 相关错误? A:Linux/macOS 的官方 Python 自带 curses;Windows 请执行 pip install windows-curses,或直接使用 CLI 子命令。

Q3:某个电台打不开 / 一直缓冲? A:直播流会失效或做地区限制。可先 airwave play <url> --json 看连接事件;确认源失效后欢迎到 Issue 标注 stream-broken

Q4:为什么录制的是 MP3 但文件能直接播? A:AirWave 录制的是剔除 ICY 元数据帧后的纯净音频字节,扩展名按流类型选择(AAC 流为 .aac),不需要二次封装。

Q5:会上传我的收听记录吗? A:不会。除了向你指定的电台地址与公开的 Radio Browser 发起请求外,没有任何遥测。


💡 设计思路与迭代规划

🏗️ 架构设计

┌──────────────┐     ┌──────────────┐
│  CLI / TUI   │────▶│  StreamPlayer │  播放引擎(线程安全、UI 无关)
└──────────────┘     └──────┬───────┘
                            ├─▶ playlists  M3U/PLS/XSPF/ASX + 嵌套解析
                            ├─▶ metadata   ICY 帧状态机 / StreamTitle
                            ├─▶ directory  Radio Browser + 内置离线目录
                            ├─▶ library    收藏 / 历史(原子 JSON)
                            └─▶ backends   mpv/ffplay/vlc/mplayer/null

关键取舍:

  1. 标准库优先urllib + http.server + curses + xml.etree 足以覆盖全部能力,换来零供应链风险与极致可移植性。
  2. 引擎与界面解耦:播放引擎只通过事件回调对外通信,因此 CLI、TUI、自动化脚本与测试共用同一条链路,行为完全一致。
  3. 永不阻塞在直播流上:播放列表解析只对“看起来像播放列表”的 URL 发起读取,直连流零预读,从设计上杜绝挂死。
  4. 后端外置:解码交给成熟播放器,AirWave 专注网络协议、元数据与录制,因此不需要绑定任何音频驱动。

🗺️ 迭代路线图

  • v1.1:电台测速与延迟排序、收藏分组、TUI 内音量调节
  • v1.2:HLS(m3u8 分片)内置 demux 录制、节目单(EPG)抓取
  • v1.3:TUI 主题/键位配置文件、桌面通知(now-playing)
  • v1.4:局域网 Web 遥控模式、Podcast RSS 订阅下载
  • 长期:更多目录源、插件机制、可选的 equalizer 后处理

🤲 社区贡献方向

欢迎认领路线图条目,也特别欢迎:新增稳定公开电台到内置目录、补充多语言翻译、完善打包(Homebrew/AUR/Scoop)。


📦 打包与部署指南

AirWave 属于工具库 / CLI 类项目(纯 Python、跨平台、无需编译原生二进制),因此以 wheel/sdist 形式分发,不发布平台可执行文件。

从源码构建分发包

pip install build
python -m build
# 产物:
#   dist/airwave_radio-1.0.0-py3-none-any.whl   (跨平台 wheel)
#   dist/airwave_radio-1.0.0.tar.gz             (源码包)

离线环境安装

把 wheel 拷贝到目标机器后:

pip install airwave_radio-1.0.0-py3-none-any.whl --no-index --find-links .
airwave --version

兼容环境矩阵

平台 CLI TUI 说明
Linux 主力验证环境(Ubuntu 22.04 / Python 3.10)
macOS 系统 Python 自带 curses
Windows ⚠️windows-curses CLI 与录制能力不受影响
无头服务器 / 容器 ✅(null 后端) 适合定时录制与元数据采集

部署为定时录制服务

# 1) 安装
pipx install airwave-radio
# 2) 验证无头链路
airwave play "FIP" --backend null --duration 5
# 3) 用 cron/systemd timer 周期执行 `airwave record ...` 即可

🤝 贡献指南

欢迎 Issue、PR 与电台源推荐!开发前请阅读 CONTRIBUTING.md:测试基于标准库 unittestPYTHONPATH=src python3 -m unittest discover -s tests),提交信息遵循 feat/fix/docs/refactor/test/chore 的 Angular 规范,且不接受新增运行时第三方依赖

📄 开源协议

本项目基于 MIT License 开源,可自由使用、修改与商用,请保留版权声明。内置目录中的电台流版权归各电台所有。

About

📻 AirWave · 零依赖终端网络电台播放器 | Zero-dependency terminal internet radio: Radio Browser directory, M3U/PLS/XSPF/ASX parsing, ICY Now-Playing, stream recording, CLI + curses TUI

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages