← 返回文章

在 AGX Orin 上用 chiaki-ng 和双账号实现 headless PS5 录制

记录从同一局域网配置、macOS 注册信息迁移、AGX Orin 编译 chiaki-ng,到实现并验证 headless ps5-recorder 的完整过程。

#AGX Orin#PS5#chiaki-ng#Remote Play#FFmpeg#Headless

在 AGX Orin 上用 chiaki-ng 和双账号实现 headless PS5 录制

这篇记录一个比较具体的折腾过程:先在 Mac 上用 chiaki-ng 完成 PS5 注册,再把配置迁移到 AGX Orin,编译出命令行版 chiaki-ng,最后用 libchiaki 写一个没有桌面界面的 ps5-recorder,把 PS5 的画面录成 Jellyfin 可以直接扫描的 Matroska 视频。

网络部分只讨论一个局域网段。示例拓扑如下:

设备 示例地址
PS5 192.168.1.20
AGX Orin 192.168.1.30
局域网 192.168.1.0/24

这里的重点不是把 PS5 暴露到公网,而是让 Orin 和 PS5 在同一个局域网段内完成发现、连接和录制。

1. 最终链路

最后得到的链路是:

Mac chiaki-ng 注册
        │ 导出 QSettings INI
        ▼
AGX Orin ~/Downloads/chiaki-ng-*.ini
        │
        ├── chiaki-cli:discover / wakeup 验证主机
        │
        └── ps5-recorder:读取注册凭据
                │
                ▼
        libchiaki Remote Play session
                │
        H.264 视频 + Opus 音频
                │
                ▼
        FFmpeg 最终封装为 MKV
                │
                ▼
        Jellyfin 媒体目录

这里有一个容易混淆的地方:chiaki-cli 能证明主机发现和唤醒链路正常,但它本身不是一个完整的无界面录制器。录制需要建立 session、接收视频和音频回调,再把数据交给文件写入器和 FFmpeg,所以最终单独实现了 ps5-recorder。

2. 双账号应该怎样处理

双账号最重要的原则是:两个账号是两套独立的注册配置,不是把两套密钥合并进一个 INI 文件。

可以把两个账号叫作 Account A 和 Account B:

  1. 在 Mac 的 chiaki-ng 中登录 Account A,完成 PS5 注册并导出配置。
  2. 切换到 Account B,完成同样的注册流程,导出另一份配置。
  3. 分别命名为 chiaki-ng-account-a.ini 和 chiaki-ng-account-b.ini。
  4. 使用哪个账号录制,就通过 --config 选择对应文件。

配置里可能包含 psn_account_id、rp_regist_key、rp_key 以及 token 等敏感字段。它们不能提交到 Git、发到聊天窗口,也不应该放进公开仓库。两个配置文件的权限都应限制为当前用户可读写:

chmod 600 ~/Downloads/chiaki-ng-account-a.ini
chmod 600 ~/Downloads/chiaki-ng-account-b.ini

一次运行只使用一个配置。这样做既避免误用账号凭据,也让输出目录可以按账号分开:

MEDIA_ROOT="$(readlink -f "$HOME/Downloads/torrents")"
mkdir -p "$MEDIA_ROOT/ps5-recorder/account-a"

PS5_RECORDER_OUTPUT_DIR="$MEDIA_ROOT/ps5-recorder/account-a" \
  ~/ps5-recorder/run.sh \
  --config "$HOME/Downloads/chiaki-ng-account-a.ini"

切换到 Account B 时,只替换配置文件和输出目录:

mkdir -p "$MEDIA_ROOT/ps5-recorder/account-b"

PS5_RECORDER_OUTPUT_DIR="$MEDIA_ROOT/ps5-recorder/account-b" \
  ~/ps5-recorder/run.sh \
  --config "$HOME/Downloads/chiaki-ng-account-b.ini"

这不是让两个账号在同一个录制进程里同时登录,而是让同一套 recorder 程序安全地选择不同账号。是否能在同一台 PS5 上切换不同用户、是否需要重新注册,仍然取决于 PS5 用户和 Remote Play 的实际状态;不要用一套账号的注册密钥去替换另一套配置里的字段。

3. 在 Mac 上注册并迁移配置

Mac 端的 chiaki-ng 适合完成需要交互的登录和注册流程。注册成功后,从设置中导出配置文件,再复制到 Orin:

scp ~/Downloads/chiaki-ng-account-a.ini \
  wooley@192.168.1.30:~/Downloads/

如果只使用一个账号,文件名也可以保持为:

~/Downloads/chiaki-ng-PS5.ini

在 Orin 上不要直接把整个 INI 打印出来。先确认文件类型、权限和大小:

file ~/Downloads/chiaki-ng-PS5.ini
stat ~/Downloads/chiaki-ng-PS5.ini
chmod 600 ~/Downloads/chiaki-ng-PS5.ini

这个导出的文件是 Qt QSettings 风格的 ASCII INI。它包含 registered_hosts、manual_hosts 等区段,主机地址和昵称可以被程序读取;二进制注册字段会以 @ByteArray(...) 形式保存,其中还可能有转义字节。不能只按普通字符串读取,需要按 QSettings 的编码规则解码。

4. 在 AGX Orin 上编译 chiaki-ng CLI

Orin 使用 aarch64 Linux,目标是保留 core 和 CLI,关闭桌面 GUI。这样可以减少 Qt 窗口系统的依赖,也方便把设备放在电视柜或机架里长期运行。

源码目录和构建目录分开:

cd ~/chiaki-ng

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DCHIAKI_ENABLE_CLI=ON \
  -DCHIAKI_ENABLE_GUI=OFF

cmake --build build -j"$(nproc)"

编译完成后,CLI 通常位于:

~/chiaki-ng/build/cli/chiaki-cli

先用 discovery 检查局域网连接:

~/chiaki-ng/build/cli/chiaki-cli \
  discover -h 192.168.1.20 -t 3

正常情况下可以看到 PS5 主机处于可用状态,并显示注册时设置的昵称。wakeup 也可以作为第二个验证点,但不要把唤醒凭据写进博客或命令历史;它应该只从本机受保护的配置中读取。

5. 给 recorder 准备非敏感环境变量

为了不把路径和主机信息重复写在每条命令里,可以创建一个只保存非敏感元数据的环境文件:

install -d -m 700 ~/.config/chiaki-ng

cat > ~/.config/chiaki-ng/ps5-recorder.env <<'EOF'
export CHIAKI_CONFIG_FILE="${HOME}/Downloads/chiaki-ng-PS5.ini"
export CHIAKI_CONFIG_FORMAT="qsettings-ini"
export CHIAKI_CLI="${HOME}/chiaki-ng/build/cli/chiaki-cli"
export CHIAKI_HOST_ADDR="192.168.1.20"
export CHIAKI_HOST_NAME="PS5"
export CHIAKI_TARGET="ps5"
EOF

chmod 600 ~/.config/chiaki-ng/ps5-recorder.env

实际文件中不要额外写入 PSN token、注册密钥或明文密码。run.sh 会自动加载这个环境文件,命令行的 --config 可以临时覆盖默认账号,正好适合双账号切换。

6. headless ps5-recorder 的实现

recorder 单独放在 ~/ps5-recorder,不直接改动 chiaki-ng 源码:

ps5-recorder/
├── CMakeLists.txt
├── main.cpp
├── run.sh
├── README.md
├── build/
└── recordings/

实现分成四层。

6.1 读取 QSettings 配置

程序读取导出的 INI,定位注册主机,并解析 @ByteArray(...) 中的十六进制和反斜杠转义。随后只做结构校验:

  • 目标必须是 PS5;
  • 主机地址必须存在;
  • 注册字段必须解码成功;
  • rp_regist_key 和 rp_key 的长度应符合 16 字节注册密钥的预期。

校验命令只输出主机、昵称、目标类型和字节数,不输出密钥内容:

~/ps5-recorder/run.sh --check-config

实际验证时可以看到类似结果:

config_ok=1
host=192.168.1.20
nickname=PS5
target=1000100
ps5=1
regist_key_bytes=16
morning_bytes=16

6.2 建立本地 Remote Play session

recorder 将解析出来的主机地址、目标类型和注册凭据转换为 ChiakiConnectInfo,请求指定的视频分辨率和帧率,然后建立本地局域网 session。

默认请求 1080p/60,也可以降低为 720p/30 来减少带宽和磁盘压力:

~/ps5-recorder/run.sh --resolution 720 --fps 30

视频回调收到 H.264 数据,音频回调收到 Opus 数据。程序不会把 PSN token 打到日志里,连接失败时只报告阶段和错误信息。

6.3 临时文件和最终封装

录制期间先写入临时的 H.264 和 PCM 文件,结束时调用系统 FFmpeg:

  • 视频直接复制,避免再次编码损失画质;
  • Opus 音频转成 AAC;
  • 最终封装为 MKV;
  • 成功后删除 .part.h264 和 .part.pcm;
  • 输出文件权限设置为 0600。

这样做比边收包边依赖复杂的实时 muxer 更容易排查问题,也能在 Ctrl-C 时执行一次正常的 finalize。--raw 可以保留原始 H.264,通常只建议在调试时使用。

6.4 退出和录制时长

指定 --duration 时,达到秒数后自动结束:

PS5_RECORDER_OUTPUT_DIR="$HOME/Downloads/ps5-recorder" \
  ~/ps5-recorder/run.sh --duration 60

这表示录制 60 秒。省略 --duration 就是持续录制,直到主动按 Ctrl-C:

PS5_RECORDER_OUTPUT_DIR="$HOME/Downloads/ps5-recorder" \
  ~/ps5-recorder/run.sh

默认文件会写到 ~/ps5-recorder/recordings/,文件名带有时间戳。连接建立本身需要一点时间,因此最终媒体时长可能比参数略短,这是启动握手发生在计时窗口内造成的。

7. 验证结果

先跑一次短测试,避免直接开启长时间录制:

~/ps5-recorder/run.sh --duration 10 \
  --output ~/ps5-recorder/recordings/smoke-test.mkv

再用 FFprobe 检查容器和轨道:

ffprobe -hide_banner \
  ~/ps5-recorder/recordings/smoke-test.mkv

实际测试得到的文件包含:

  • H.264 视频,1920×1080;
  • AAC 音频,48 kHz、双声道;
  • Matroska 容器;
  • Ctrl-C 结束后仍能正常播放;
  • 正常结束后没有残留 .part.* 文件。

这说明从配置解析、局域网 session、视频/音频回调到最终封装的链路已经闭合。原始 chiaki-ng 工作树保持干净,recorder 是独立的小项目,后续升级 chiaki-ng 时可以分别验证。

8. 让 Jellyfin 扫描到录制文件

之前直接在 Downloads 下再套一层软链接时,Jellyfin 可能因为容器挂载路径、扫描策略或权限,看不到最终文件。更稳妥的方式是解析 ~/Downloads/torrents 的真实目标,把 recorder 直接写进真实的媒体目录:

MEDIA_ROOT="$(readlink -f "$HOME/Downloads/torrents")"
mkdir -p "$MEDIA_ROOT/ps5-recorder"

PS5_RECORDER_OUTPUT_DIR="$MEDIA_ROOT/ps5-recorder" \
  ~/ps5-recorder/run.sh

这里的关键是 readlink -f:如果 Downloads/torrents 本身已经指向 media,程序就直接使用 media/ps5-recorder,不再创建“软链接里面再套软链接”的路径。

如果 Jellyfin 运行在 Docker 中,还要确认这个真实目录已经映射进容器,并且容器用户对它有读取权限。Jellyfin 看到的路径必须是容器内的挂载路径,而不是 Orin 宿主机上的路径字符串。

双账号也可以沿用这个目录结构:

media/
└── ps5-recorder/
    ├── account-a/
    └── account-b/

这样两个账号的录制文件不会混在一起,Jellyfin 也可以按目录组织媒体。

9. 这套方案的边界

这套实现适合一个局域网内的长期录制节点,但仍有几个边界:

  • chiaki-cli 不是 recorder,不能只靠 CLI 命令完成视频采集;
  • 配置文件是账号和主机的敏感凭据,必须保存在受保护的本机路径;
  • 双账号要保持两份完整配置,不能手工拼接字段;
  • 一个 recorder 进程一次只使用一个账号配置;
  • PS5 休眠、用户切换或系统更新后,可能需要重新确认 Remote Play 注册状态;
  • 录制程序目前以本地网络和 FFmpeg 为前提,不负责公网穿透或跨网段连接。

对我来说,这次最有价值的结果不是又做了一个 GUI,而是把一次性的桌面注册流程拆成了三个可验证的阶段:先用 chiaki-ng 注册,再用 chiaki-cli 验证主机,最后由一个很小的 headless recorder 完成持续录制。以后换账号、换输出目录或接入 Jellyfin,都只需要替换明确的配置和路径,不必重新改动核心代码。

Conversation

留言

加载中

正在读取留言…

Leave a note

留下你的想法

留言提交后会先进入审核,审核通过才会公开显示。