Skip to content

Repository files navigation

casting-rec

通过 DLNA / AirPlay / Cast 投屏协议捕获手机直播流,录制到本地磁盘,方便后续剪辑、回看、存档。

主程序是 PySide6 GUI(无需 Python 知识即可上手),wechat-finder-dlna 作为外部 Python 依赖安装,不把第三方源码复制到本仓库。

版权与许可证

Copyright (C) 2026 vark-debug。

本项目以 GNU General Public License v3.0 或更高版本(GPL-3.0-or-later) 发布,详见 LICENSE

项目内置了 FFmpeg / FFprobe 二进制。该构建启用了 GPL 编解码器,因此随本项目分发的 FFmpeg 部分适用 FFmpeg 的 GPL 条款;FFmpeg 及其相关组件的版权归原作者和 FFmpeg 项目所有。FFmpeg 源码和许可证信息见 FFmpeg 官方仓库FFmpeg GPL 许可文件GPLv3 许可证

第三方项目致谢

感谢 gtoxlili/wechat-finder-dlna 提供视频号投屏直播流捕获能力。本项目通过 PyPI 依赖 wechat-finder-dlna>=0.4.3 使用该项目,不包含其源码;其许可证和版权归原项目作者所有。


系统架构

┌─────────────────┐   投屏    ┌─────────────────────┐
│ 微信视频号(手机)│ ───────► │  wechat-finder-dlna │
└─────────────────┘           │ (伪装成电视接收投屏)│
                              └────────┬────────────┘
                                       │ m3u8 URL
                                       ▼
┌──────────────────────────────────────────────────────────┐
│                    casting-rec (PySide6 GUI)             │
│  • ffmpeg FEED  → UDP 9999(监看流,全程不中断)         │
│  • ffmpeg REC   → out/casting_<ts>_part_NNN.ts(录制)   │
│  • 切段:双 REC 重叠,旧 REC 缓冲 3 秒优雅退出           │
│  • 自动 remux:切段/停止时把对应 .ts 转 .mp4             │
└──────────────────────────────────────────────────────────┘

目录结构

casting-rec/                       ← 项目根目录
├── casting_rec/                   ← Python 包(应用代码)
│   ├── __main__.py
│   ├── main.py                    ← GUI 入口
│   ├── core/
│   │   ├── recorder.py            ← ffmpeg + 状态机
│   │   ├── process.py             ← ffmpeg 子进程封装
│   │   └── state.py
│   ├── ui/
│   │   └── main_window.py
│   └── vendor/
│       └── ffmpeg/                ← 内置 ffmpeg 二进制(被打包进 .app)
│           ├── ffmpeg-aarch64-apple-darwin
│           └── ffprobe-aarch64-apple-darwin
│
├── scripts/
│   └── prototypes/                ← 原型 shell 脚本(归档,不再使用)
│       ├── record.sh              ← 单场连续录制
│       ├── manual_cut.sh          ← 按 q 键切段
│       └── prepare.sh             ← TS → MP4 (守护模式)
│
├── tests/
│   └── smoke_cut_segment.py       ← Phase B 切段联调烟雾测试
│
├── casting-rec.spec               ← PyInstaller 打包配置
├── pysidedeploy.spec              ← pyside6-deploy 备用打包配置
├── pyproject.toml
├── LICENSE                       ← 项目 GPL-3.0-or-later 许可证
└── README.md

日常使用(GUI 版)

给最终用户

1. 拿到 casting-rec.dmg,双击挂载
2. 把 casting-rec.app 拖进 /Applications
3. 双击启动(首次启动被 Gatekeeper 拦截 → 右键 → 打开)
4. 默认输出目录在 ~/Library/Application Support/casting_rec/out
   点 "浏览…" 可改到自己想存的目录
5. 点 "⏺ 开始录制" → 手机微信投屏选择 MAGI → 自动录
6. 录制中可点 "✂️ 切段" 分段,点 "⏸ 停止录制" 结束

发布版无需安装 ffmpeg:FFmpeg / FFprobe 已随 casting_rec/vendor/ffmpeg/ 一起打包进 casting-rec.app/Contents/Frameworks/

已验证环境

  • macOS Apple Silicon(arm64,M1 / M2 / M3 / M4 等)
  • 系统未安装 FFmpeg,未依赖 Homebrew 或系统 PATH
  • casting-rec.app 已验证可正常启动并录制,运行时实际调用的是应用包内置的 FFmpeg / FFprobe

给开发者

装依赖

# 在 casting-rec 项目根目录执行
python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

启动 GUI(开发模式)

source venv/bin/activate
python -m casting_rec

GUI 会优先使用应用包内置的 FFmpeg / FFprobe;开发模式下使用 casting_rec/vendor/ffmpeg/ffmpeg-aarch64-apple-darwin,找不到时才 fallback 到系统 PATH。

跑测试

source venv/bin/activate
python tests/smoke_cut_segment.py

打包成 .app

source venv/bin/activate
pyinstaller --noconfirm casting-rec.spec

产物:dist/casting-rec.app —— 双击即可运行,目标机器无需 Python / ffmpeg


关键设计原则

1. 真解耦 FEED + REC 双进程

  • FEED ffmpeg:拉 m3u8 → 推 UDP 9999,永不停,提供监看流(ffplay / VLC / GUI 内置 QMediaPlayer)
  • REC ffmpeg:拉 m3u8 → 写 .ts 文件,按段启停

切段时,旧 REC 缓冲 3 秒再 SIGTERM(保证 moov/sync 数据写完),新 REC 1-2 秒接管,监看画面全程不抖

2. TS 比 MP4 安全

mp4 用 moov 原子(索引),需要"先写数据、再写索引"两遍。流式录制中断在第二遍 → mp4 损坏。 TS 每个 packet 自带时间戳,崩溃安全。所以策略是:录制用 TS,切段/停止时自动 remux 成 MP4。

3. 内置 ffmpeg

casting_rec/vendor/ffmpeg/ffmpeg-aarch64-apple-darwin 是单文件静态链接的 Mach-O 二进制(~52 MB), 不依赖任何外部动态库。PyInstaller spec 通过 binaries=[...] 把它塞进 .app/Contents/Frameworks/

Recorder._find_ffmpeg() 查找顺序:

  1. vendor 路径(开发 + .app 模式都支持)
  2. shutil.which("ffmpeg")
  3. homebrew / 系统兜底路径

4. caffeinate 防休眠(macOS only)

caffeinate -dis 绑定到 Recorder 子进程;退出时自动 SIGTERM 回收。

5. SIGTERM 优雅退出

ffmpeg 收到 SIGTERM → 做最后清理 → 退出。配合 3 秒超时 + SIGKILL 兜底。


录制文件命名

casting_YYYYMMDD_HHMMSS_part_001.ts   ← 第 1 段
casting_YYYYMMDD_HHMMSS_part_002.ts   ← 第 2 段
...
casting_YYYYMMDD_HHMMSS_part_001.mp4  ← 自动 remux
casting_YYYYMMDD_HHMMSS_part_002.mp4
...

常见问题

Q1: 手机搜不到 MAGI 设备?

  • 手机和电脑同一 WiFi
  • macOS 防火墙允许 Python 监听
  • iOS 微信可能只走 AirPlay(GUI 内部三种协议都开)

Q2: 录制中 ffmpeg 报 Non-monotonic DTS

正常,ffmpeg 自动修正,文件可播。

Q3: 关闭终端会不会中断录制?

GUI 版不受终端影响。要后台跑用 nohup python -m casting_rec &

Q5: 多段怎么拼接?

GUI 已自动 remux 每段;如需拼一段完整视频,用 ffmpeg -i "concat:casting_xxx_part_001.ts|casting_xxx_part_002.ts|..." -c copy casting_xxx_full.ts。 段间有 3 秒重叠(缓冲期),拼接后中间会有重复帧——用剪辑软件修一下即可。


系统要求

  • macOS 11.0+(caffeinate + BUNDLE 格式)
  • Apple Silicon(当前发布版使用 arm64 内置 FFmpeg / FFprobe;Intel 版本尚未提供)
  • Python 3.11+(开发模式需要)

依赖版本

  • casting-rec 0.1.0(macOS arm64)
  • PySide6 >= 6.6
  • pyinstaller >= 6.0
  • wechat-finder-dlna >= 0.4.3(GitHub 仓库,感谢原作者)
  • FFmpeg / FFprobe(应用内置,GPL 构建)

最后更新:2026-09-05(已验证无系统 FFmpeg 的 Apple Silicon Mac 可使用应用内置 FFmpeg)

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages