cf53afd7c8
fix: improve HLS audio track discovery - async load fallback + detailed diagnostics
...
- setupAudioTap: log all tracks at start, KVO count changes
- findAudioTrackID: log when assetTrack is nil (HLS not loaded)
- Polling: add async asset.load(.tracks) fallback after 5s
- Extend timeout from 20s to 30s
- Status log every 5s during polling
2026-06-25 20:51:27 +08:00
8cfb072370
fix: HLS audio via KVO+polling for playerItem.tracks, diagnostic logging
...
- KVO观察playerItem.tracks变化(HLS tracks异步加载)
- 轮询保底(20秒超时),KVO不触发时仍能捕获
- 诊断日志:打印每个track的mediaType/trackID
- tap回调改进:始终先GetSourceAudio保证管道不阻塞
- 窗口标题随toolbar联动
2026-06-25 09:12:02 +08:00
be0cf09941
fix: HLS audio (playerItem.tracks + better tap callback) + window title sync with toolbar
...
- HLS录制音频: 改用playerItem.tracks查找trackID(fallback到asset.loadTracks)
- tap回调: 始终先调GetSourceAudio保证管道畅通,加详细日志
- 窗口标题: onAppear初始隐藏,随toolbar一起30秒后消失/点击图标回来
2026-06-25 09:08:02 +08:00
fc95254500
feat: 录制完成后弹出保存对话框,支持用户改名
...
- 添加 showSaveDialog 方法,使用 NSSavePanel
- 默认文件名为 Recording_时间戳.mp4
- 用户可修改文件名或选择保存位置
- 点击取消(X)时删除临时文件
- 保存成功后调用 onRecordingSaved 回调
2026-06-25 08:56:47 +08:00
ff20ffe07f
fix: HLS音频录制+边录边写+结束仅改名移动
...
1. 修复HLS无声音:
- 统一回调函数签名,删除重复定义
- 回调函数名改为 tapInitCallback/tapFinalizeCallback 等避免歧义
- 添加NSLog诊断日志
2. 边录边写文件:
- AVAssetWriter直接写入临时文件(边录边写,不缓存内存)
- 临时文件名用时间戳,避免冲突
3. 录制结束仅改名移动:
- finishWriting完成后直接moveItem到最终文件名
- 不再弹NSSavePanel
- 最终文件名格式:Recording_yyyy-MM-dd_HH-mm-ss.mp4
- 保存到 ~/Movies/MiniPlayer/
2026-06-25 08:29:39 +08:00
d9f12ced06
fix: MTAudioProcessingTapCallbacks参数名initCallback→init
...
修复编译错误:Swift bridging 期望的参数名是 init 而非 initCallback
2026-06-24 23:16:08 +08:00
5ae4cc4e70
feat: HLS流音频录制——MTAudioProcessingTap替代AVAssetReader
...
问题: AVAssetReader不支持HLS流(m3u8),录制HLS时音频丢失。
方案: 统一使用MTAudioProcessingTap捕获音频
- 从播放管道直接获取PCM音频数据,本地文件和HLS流通用
- tap回调通过MTAudioProcessingTapGetSourceAudio获取源音频+时间范围
- AudioCaptureContext通过Unmanaged传递给C回调
- init/finalize回调管理context生命周期
- 视频仍用AVPlayerItemVideoOutput(已验证稳定)
API变更:
- startRecording(from:playerItem:startTime:) 替代 sourceURL
- PlayerBridge传入playerItem而非URL
2026-06-24 23:14:47 +08:00
c7bb63bb7e
fix: HLS播放加自定义headers + 录制finishWriting错误日志
...
HLS播放:
- AVURLAsset替代AVPlayerItem(url:),加Referer/UA headers
- 某些HLS流服务端校验Referer,裸URL请求被拒绝
录制:
- startWriting检查返回值和error
- finishWriting回调打印status/error/frames
- 失败时删除损坏的临时文件,弹出错误提示
2026-06-24 22:59:44 +08:00
ff4902ffe6
fix: 视频只有一帧+音频超长——重写录制时间基准和音频限速
...
视频修复:
- startSession(atSourceTime: .zero) 替代 itemTime
- 之前 session 起点是绝对 itemTime(如120s),但 sample 时间戳
是相对的(0, 1/30...),writer 因 0<120 丢弃帧
- 现在统一用 player.currentTime() 作为共享时间基准
音频修复:
- 用 DispatchSourceTimer(20ms) 替代 requestMediaDataWhenReady
- 每 20ms 检查实时进度(elapsed wall-clock),只写入不超前的音频
- 超前的 sample 缓存到 pendingAudioSample 等下次 tick
- 停止时 cancel timer + cancel reader,音频长度精确对齐视频
音视频同步:
- 两者共享 recordStartTime = player.currentTime()
- 视频: itemTime - recordStartTime
- 音频: audioPTS - recordStartTime
2026-06-24 22:08:09 +08:00
06345b07de
fix: 视频只有一帧 + 音频长度不对
...
视频修复:
- 移除 hasNewPixelBuffer 依赖,改为缓存 lastPixelBuffer
- 每 1/30s 始终写入帧(新帧或复用上一帧),确保静态场景也持续输出
- 加 isRunning 检查防止停止后继续写入
音频修复:
- 用 requestMediaDataWhenReady 替代 busy-loop
- writer 控制读取节奏,不再一次性读完全部源音频
- stopRecording 时 cancelReading + markAsFinished 立即停止
音视频同步:
- 视频用 itemTime 相对 firstFrameTime 的时间戳
- 音频用源文件 pts 相对 firstFrameTime 的时间戳
- 两者共享同一时间基准
2026-06-24 21:19:10 +08:00
42f3cf2b84
fix: 音视频同步——音频从 firstFrameTime 开始读取
...
之前音频用 player.currentTime() 作为起始时间,视频用
AVPlayerItemVideoOutput 的 firstFrameTime,两者可能不一致
导致音视频不同步。
改为:
- prepareAudioCapture: 只预加载音频轨道,不立即开始读取
- captureVideoFrame: 第一帧时设置 firstFrameTime 后调用
beginAudioReading(startTime: firstFrameTime)
- 音频和视频共用同一个时间基准,确保精确同步
- 移除 startRecording 的 startTime 参数
2026-06-24 21:07:07 +08:00
60a3369d82
fix: 录制停止时音频未同步停止导致输出文件超长
...
根因: readAudioLoop 从文件读音频速度远快于实时,每帧 dispatch 到
MainActor 造成大量 Task 积压。用户点停止时,积压的 Task 在
isRunning=false 生效前全部执行,导致整个源音频被写入。
修复:
- 音频直接在后台队列写入,不再 dispatch 到 MainActor
- 增加 nonisolated(unsafe) audioStopped 标志,stopAudioCapture
先设标志让 loop 立即退出
- 增加 nonisolated(unsafe) audioFirstFrameTime 供后台线程读取
- audioInput 作为参数传入 readAudioLoop,避免跨 actor 访问
2026-06-24 21:01:39 +08:00
cbc03b40b4
Fix: use Timer for video capture, set isRunning before capture loop
2026-06-24 20:44:51 +08:00
6c31894a6d
Fix: record audio from source URL, not microphone
2026-06-24 20:28:31 +08:00
5d9e93ba95
Record video source via AVPlayerItemVideoOutput, not screen capture
2026-06-24 20:04:08 +08:00