惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

云风的 BLOG
云风的 BLOG
Blog — PlanetScale
Blog — PlanetScale
博客园 - 【当耐特】
博客园_首页
The GitHub Blog
The GitHub Blog
月光博客
月光博客
Hugging Face - Blog
Hugging Face - Blog
有赞技术团队
有赞技术团队
博客园 - 三生石上(FineUI控件)
D
Docker
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
酷 壳 – CoolShell
酷 壳 – CoolShell
雷峰网
雷峰网
小众软件
小众软件
I
InfoQ
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky

V2EX

我用 AI 写代码,但终端管理反而成了累赘——于是我做了 codux [调研] 各位在公司都用什么 ide 和 agent 写代码? 老运维 share 一个运维平台 看到有公司考核 token 指标,很好奇大家上个月的 AI 账单是多少 GLM-Coding 调用持续报错: z.ai 的 Lite 套餐几乎无法使用,官方 Pro/Max 是否稳定? 现在还有什么渠道可以稳定安全地使用 Claude 吗? 上海漕河泾内推,本组有 2 个 hc,一个后端,一个前端,预算都是 20k 左右,不打卡,氛围好 如果 V2EX 上有一组不永久保存聊天记录(比如只保存 7 天或者 24 小时)的聊天室,那么会开启哪些有用或者有趣的可能? gemini cli 貌似挂了,一直返回 403 第一次在自媒体上赚到钱 收集了最近在使用的低价 GPT, Gemini,邮箱等 AI 会员的小店合集 讨论个大实话:现在企业还在说 AI 编程提效 20%, 30%的,真的太落后,没用懂 AI。因为包括很多前沿公司,已经狂奔到提效 200%-500%的情况 [招聘][远程][币安] 前端/后端/QA/iOS/Android 至少 3 年以上经验 目前有大量 HC 欢迎投递 Chatgpt Pro 用量用不完的可以开这些设置 面试的时候好像遇到钓鱼了,给各位避个坑 cursor 年续费 22 号到期, 自动续费是否还是老的计次套餐呢 被两件破事毁掉的一下午,琐碎的内耗消磨人的精力 使用 Planet 存储 Codex 的会话或者重要信息 如果业务部门领导不要你开发功能,而是要求你教会它用 claude code 开发功能,你会怎么做? 分享一个 MacOS 接绿联 CM818 USB 转 DP 转接器使用感受 我的 HR 朋友 10 年老 Java ,非全大专,大家帮忙看看简历 开源了一个 AI 口语练习工具,音素级发音评分,完全免费可自部署 V2EX 上有哪些你觉得很有趣、印象深刻的妹纸? 字节为啥不出个国内版 Vercel? 有在大马的朋友吗? 问个运营商问题 你们在有领导的公司大群发过的最大胆的消息是什么 公司裁员,目前没有工作。想试试摆摊,做一个移动鲜啤打酒车 我的硬盘 Memblaze Pblaze 5 Linux 下不识别,给 Linux 内核提交了补丁, AI 说有望被合并 只有我一个人觉得 codex 不好用?
独立开发日记:今天给「静听」音乐播放器做了十几个优化
kfj92 · 2026-03-09 · via V2EX

独立开发日记:今天给「静听」音乐播放器做了十几个优化

项目背景

「静听」是我独立开发的一款 iOS 本地音乐播放器,主打无损格式支持、WiFi 传歌、无广告体验。开发一年多了,一直在持续优化。

今日优化清单

🎵 播放体验修复

  1. 单曲循环 bug:之前循环播放时只重复最后几秒,现已修复
  2. 随机播放逻辑:优化了算法,现在是真正的全曲库随机
  3. 播放连续性:歌曲播完后自动切下一首,逻辑更符合直觉
  4. 播放时间显示:修复了偶尔「卡住」不走的罕见问题

🎧 蓝牙交互优化

  1. 蓝牙自动恢复:连接蓝牙耳机自动继续播放,断开自动暂停
  2. Siri 兼容性:修复了唤起 Siri 时闪退的问题
  3. 音频中断处理:微信语音等中断后智能恢复播放位置

📱 UI/UX 细节

  1. 歌单封面:无封面歌单自动显示第一首歌的封面
  2. 静默刷新:修改歌曲信息后列表自动刷新,无闪烁
  3. 播放队列定位:新增「一键定位」到当前播放歌曲
  4. 工具栏同步:底部工具栏播放模式修改即时生效

🔧 核心功能

  1. WiFi 传歌:增加取消导入功能,修复重复导入跳过逻辑
  2. 编辑页面:优化封面保存逻辑,不再保存占位图
  3. 歌词显示:修复导入的歌词文件显示空白的问题

🛠️ 技术底层

  1. 音频引擎:换用 ffmpeg ,支持更多音频格式
  2. 状态同步:播放模式修改后全局同步更新
  3. 状态恢复:重启 App 正确记住播放状态和队列
  4. 批量管理:页面底部显示筛选后的歌曲总数

技术细节分享

单曲循环修复

问题出现在 AVPlayertimeObserver 回调时机处理上。原逻辑在歌曲即将结束时就开始准备循环,导致只播放最后几秒。

解决方案:

// 修复后的逻辑
player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: .main) { [weak self] time in
    guard let self = self else { return }
    let currentTime = CMTimeGetSeconds(time)
    let duration = CMTimeGetSeconds(self.player.currentItem?.duration ?? CMTime.zero)
    
    // 在歌曲结束前 0.1 秒开始准备循环
    if duration - currentTime < 0.1 && self.playMode == .singleLoop {
        self.seek(to: 0)
        self.play()
    }
}

蓝牙中断处理

iOS 的音频会话管理比较 tricky ,特别是蓝牙设备连接/断开时的状态恢复。

关键代码:

// 监听蓝牙状态变化
NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleAudioRouteChange),
    name: AVAudioSession.routeChangeNotification,
    object: nil
)

@objc func handleAudioRouteChange(notification: Notification) {
    guard let userInfo = notification.userInfo,
          let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
          let reason = AVAudioSession.RouteChangeReason(rawValue: reasonValue) else {
        return
    }
    
    switch reason {
    case .newDeviceAvailable: // 新设备可用(如连接蓝牙)
        if shouldResumePlayback {
            resumePlayback()
        }
    case .oldDeviceUnavailable: // 旧设备不可用(如断开蓝牙)
        pausePlayback()
        savePlaybackPosition()
    default:
        break
    }
}

播放模式全局同步

使用 UserDefaults + NotificationCenter 实现状态同步:

// 设置播放模式时
UserDefaults.standard.set(playMode.rawValue, forKey: "currentPlayMode")
NotificationCenter.default.post(name: .playModeChanged, object: playMode)

// 各处监听
NotificationCenter.default.addObserver(
    self,
    selector: #selector(updatePlayModeUI),
    name: .playModeChanged,
    object: nil
)

遇到的问题和解决方案

1. 随机播放只在几首歌里随机

问题:原算法使用了 Array.shuffled(),但在每次切歌时都重新 shuffle ,导致随机性不够。

解决:改为一次性 shuffle 整个播放队列,然后顺序播放。

2. 播放时间偶尔不走

问题AVPlayertimeObserver 在某些情况下(如后台播放、网络波动)会停止回调。

解决:增加保活机制,定期检查播放状态,必要时重新添加 observer 。

3. 编辑页面封面逻辑

问题:用户不选择封面时,系统会保存一个占位图,导致不必要的存储。

解决:判断用户是否真的选择了新封面,如果没有,保持原封面或使用默认 App logo 。

开发感悟

做独立开发最有趣的地方就是这些「小修小补」。每个 bug 的修复、每个体验的优化,都能让产品更接近「完美」。

今天修复的这些问题,大多都是用户反馈或自己使用中发现的。有时候一个看似简单的「继续播放」逻辑,背后涉及音频会话管理、状态恢复、用户体验等多个方面。

下一步计划

  1. 批量管理筛选:增加按专辑、艺术家、最近播放等筛选功能
  2. 播放列表管理:优化播放列表的创建、编辑、分享功能
  3. 音频效果:考虑增加更多均衡器预设和音效
  4. 多设备同步:研究 iCloud 同步播放列表和播放进度的可行性

讨论点

  1. 大家在使用音乐播放器时,最在意哪些功能或细节?
  2. 对于本地音乐播放器,还有什么功能是你们觉得必备的?
  3. 在音频播放和蓝牙设备兼容性方面,有什么经验或坑可以分享?

静听 - 无损音乐播放器 & 本地传歌 App Store: [搜索「静听」即可下载] GitHub: [暂未开源,考虑中]

欢迎交流讨论!