UxPlay 录屏与播放方案笔记

一、UxPlay 录屏音画不同步问题

问题本质

UxPlay 录制文件音画不同步,根源在录制管线本身,不在播放器。

  • AirPlay 镜像模式下,音频和视频独立传输,iOS 客户端会主动为音频流引入缓冲延迟。
  • UxPlay 的 -vsync 是播放同步选项,通过丢弃视频帧来保持实时同步,并非录制修正选项。
  • -vsync no 关闭时间戳同步,录制流畅但音画对齐完全放弃,客户端初始延迟被原样固化进文件。
  • 十几秒的延迟属于 iOS 客户端自身引入的音频缓冲,远超 -vsync 参数可补偿范围,录制时无法修复。

与系统时间的关系

UxPlay 同步依赖客户端(iPhone)通过 NTP 同步过来的时钟和音视频包时间戳,与服务器系统时间无关。

本地播放器正常、网页播放器不同步的原因

  • PotPlayer、VLC 解码器容错能力强,能自动修正不规则时间戳。
  • nowen-video 走 HLS 转码链路,对时间戳规范性要求严格,会强行插入静音帧或调整时间基准,反而破坏音画平衡。

二、落地方案

方案一:录制后 FFmpeg 修正音频延迟

确定延迟秒数后,用 itsoffset 将音频整体后移:

ffmpeg -i 原始录制.mp4 -itsoffset 12 -i 原始录制.mp4 -map 0:v -map 1:a -c copy 修正后.mp4

延迟量固定时可批量处理:

for f in *.mp4; do
  ffmpeg -i "$f" -itsoffset 12 -i "$f" -map 0:v -map 1:a -c copy "fixed_$f"
done

方案二:去掉音频,只保留视频

ffmpeg -i "输入文件.mp4" -c:v copy -an "输出文件.mp4"

音频损坏导致报错时:

ffmpeg -err_detect ignore_err -i "输入文件.mp4" -c:v copy -an "输出文件.mp4"

视频流也有时间戳问题时:

ffmpeg -err_detect ignore_err -i "输入文件.mp4" -c:v libx264 -preset fast -crf 23 -an -movflags +faststart "输出文件.mp4"

批量处理:

mkdir -p fixed
for f in *.mp4; do
  ffmpeg -err_detect ignore_err -i "$f" -c:v copy -an "fixed/$f"
done

方案三:规范化时间戳,适配 HLS 播放

ffmpeg -i "原始录制.mp4" -af aresample=async=1000 -c:v copy "修复后.mp4"
  • -c:v copy:视频流不重新编码,画质无损。
  • -af aresample=async=1000:重新采样音频,使音频样本时间戳与视频帧严格对齐,消除音频间隙。

三、替代方案评估

AirPlay 接收器替代品

项目说明
RPiPlay面向树莓派,已停止更新两年
shairport-sync仅音频,不支持视频镜像
goplay2仅音频,更新停滞
java-airplay-serverJava 实现,功能有限
airplayreceiverC# 实现,主要用于测试

结论:不存在能在录制时自动解决音画不同步的开源 AirPlay 接收器,UxPlay 已是该领域最活跃项目。

浏览器录屏方案(绕开 AirPlay 录制管线)

  • SendRec:开源 Loom 替代品,浏览器内 getDisplayMedia 录屏,优先输出 MP4,天然适配网页播放。
  • OpenLoom:自托管浏览器录屏扩展,录制后上传自有存储。
  • Direct Studio:支持导出 MP4 和 HLS 格式。

适用场景:仅需录屏并在网页回看,可放弃 AirPlay 路线。

四、nowen-video 部署要点

Podman Compose 配置

version: '3.8'

services:
  nowen-video:
    image: docker.io/cropflre/nowen-video:latest
    container_name: nowen-video
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - NOWEN_SECRETS_JWT_SECRET=可选手动指定,不设置则首次启动自动生成
      - NOWEN_LOGGING_LEVEL=info
    volumes:
      - ./data:/data
      - ./cache:/cache
      - /path/to/your/media:/media:ro
    devices:
      - /dev/dri:/dev/dri  # 无核显则删除

关键说明

  • 镜像版本 1.3.4,内部端口 8080,数据目录 /data,缓存目录 /cache。
  • 默认管理员账号 admin,密码 admin123,登录后立即修改。
  • NOWEN_SECRETS_JWT_SECRET 不设置时自动生成并持久化到数据目录;手动生成用 openssl rand -base64 32。
  • 媒体库路径必须填容器内路径 /media,不能填宿主机路径。
  • 媒体目录建议单独建视频专用目录,避免混合非视频文件。

媒体库为空排查

  1. 进入容器确认文件可见:podman exec -it nowen-video ls -lah /media
  2. 检查添加媒体库时填写的路径是否为容器内路径。
  3. 检查 PUID/PGID 与宿主机文件所有者是否一致。

五、VLC 容器方案(用于正常播放录屏文件)

Podman Compose 配置

version: '3.8'

services:
  vlc:
    image: docker.io/jlesage/vlc:latest
    container_name: vlc
    restart: unless-stopped
    ports:
      - "5800:5800"
      # - "5900:5900"
    environment:
      - TZ=Asia/Shanghai
      - USER_ID=1000
      - GROUP_ID=1000
      - DISPLAY_WIDTH=1920
      - DISPLAY_HEIGHT=1080
      - WEB_AUDIO=1
      - VNC_PASSWORD=
    volumes:
      - ./config:/config
      - /path/to/your/media:/storage
    devices:
      - /dev/dri:/dev/dri  # 无核显则删除

关键说明

  • Web 界面端口 5800,VNC 端口 5900。
  • WEB_AUDIO=1 必须开启,否则浏览器无声音。
  • 媒体目录挂载到 /storage,在 Web 界面中从该目录选择文件。
  • VLC 容器使用完整桌面版 VLC 解码器,对不规则时间戳容错能力强,播放 UxPlay 录制文件同步表现与本地 VLC 一致。

六、UXPlay 命令参考

当前使用命令:

command: >
  sh -c "uxplay -mp4 /recordings/screen_$(date +%Y%m%d_%H%M%S).mp4 -p -vsync no"

参数说明:

  • -mp4:录制为 MP4 文件。
  • -p:保留音视频流。
  • -vsync no:关闭时间戳同步,录制流畅但音画对齐放弃。
  • -vd avdec_h264:强制软件解码,CPU 占用高,已不推荐。

结论:-vsync 系列参数无法补偿十几秒级别的客户端音频延迟,录制后 FFmpeg 修正仍是唯一可靠路径。

标签: none

添加新评论