视频播放进度同步:Kazumi 多设备间进度共享实现
你是否遇到过这样的困扰:在手机上看番看到一半,切换到电脑端继续观看时,却发现播放进度需要重新查找?Kazumi 的视频播放进度同步功能彻底解决了这一问题,让你在多设备间无缝接续精彩剧情。本文将详细介绍 Kazumi 如何通过 WebDAV 协议实现播放进度的跨设备同步,以及背后的技术实现细节。
同步功能架构概述
Kazumi 的进度同步功能基于 WebDAV(Web-based Distributed Authoring and Versioning)协议实现,通过将本地播放历史数据加密存储到 WebDAV 服务器,实现多设备间的数据共享。核心实现涉及两个关键模块:
- WebDAV 客户端实现:lib/utils/webdav.dart
- 本地存储与数据处理:lib/utils/storage.dart
这两个模块协同工作,完成数据的备份、恢复和冲突解决,确保各设备间的播放进度保持一致。
数据同步实现原理
WebDAV 客户端核心实现
Kazumi 的 WebDAV 客户端封装在 WebDav 类中,位于 lib/utils/webdav.dart。该类实现了与 WebDAV 服务器的通信,包括初始化连接、数据上传、下载和同步等功能。
初始化连接的关键代码如下:
Future<void> init() async {
var directory = await getApplicationSupportDirectory();
webDavLocalTempDirectory = Directory('${directory.path}/webdavTemp');
Box setting = GStorage.setting;
webDavURL = setting.get(SettingBoxKey.webDavURL, defaultValue: '');
webDavUsername = setting.get(SettingBoxKey.webDavUsername, defaultValue: '');
webDavPassword = setting.get(SettingBoxKey.webDavPassword, defaultValue: '');
if (webDavURL.isEmpty) {
throw Exception('请先填写WebDAV URL');
}
client = webdav.newClient(
webDavURL,
user: webDavUsername,
password: webDavPassword,
debug: false,
);
client.setHeaders({'accept-charset': 'utf-8'});
try {
await client.ping();
try {
await client.mkdir('/kazumiSync');
if (!await webDavLocalTempDirectory.exists()) {
await webDavLocalTempDirectory.create(recursive: true);
}
initialized = true;
KazumiLogger().log(Level.info, 'webDav backup directory create success');
} catch (_) {
KazumiLogger().log(Level.error, 'webDav backup directory create failed');
rethrow;
}
} catch (e) {
KazumiLogger().log(Level.error, 'WebDAV ping failed: $e');
rethrow;
}
}
这段代码首先从本地存储中读取 WebDAV 服务器配置信息,然后创建 WebDAV 客户端并测试连接。成功连接后,会在服务器上创建一个名为 kazumiSync 的目录,用于存储同步数据。
播放历史数据同步流程
播放历史数据的同步主要通过 updateHistory 和 downloadAndPatchHistory 两个方法实现:
Future<void> updateHistory() async {
if (isHistorySyncing) {
KazumiLogger().log(Level.warning, 'History is currently syncing');
throw Exception('History is currently syncing');
}
isHistorySyncing = true;
try {
await update('histories');
} catch (e) {
KazumiLogger().log(Level.error, 'webDav update history failed $e');
rethrow;
} finally {
isHistorySyncing = false;
}
}
Future<void> downloadAndPatchHistory() async {
if (isHistorySyncing) {
KazumiLogger().log(Level.warning, 'History is currently syncing');
throw Exception('History is currently syncing');
}
isHistorySyncing = true;
String fileName = 'histories.tmp';
try {
final existingFile = File('${webDavLocalTempDirectory.path}/$fileName');
await download('histories');
await GStorage.patchHistory(existingFile.path);
} catch (e) {
KazumiLogger()
.log(Level.error, 'webDav download and patch history failed $e');
rethrow;
} finally {
isHistorySyncing = false;
}
}
updateHistory 方法负责将本地的播放历史数据上传到 WebDAV 服务器,而 downloadAndPatchHistory 方法则从服务器下载最新的历史数据,并与本地数据进行合并。
数据冲突解决策略
当多个设备同时修改播放进度时,可能会产生数据冲突。Kazumi 采用基于时间戳的冲突解决策略,总是保留最新的播放进度。这一逻辑在 lib/utils/storage.dart 的 patchHistory 方法中实现:
static Future<void> patchHistory(String backupFilePath) async {
final backupFile = File(backupFilePath);
final backupContent = await backupFile.readAsBytes();
final tempBox = await Hive.openBox('tempHistoryBox', bytes: backupContent);
final tempBoxItems = tempBox.toMap().entries;
for (var tempBoxItem in tempBoxItems) {
if (histories.get(tempBoxItem.key) != null) {
if (histories
.get(tempBoxItem.key)!
.lastWatchTime
.isBefore(tempBoxItem.value.lastWatchTime)) {
await histories.delete(tempBoxItem.key);
await histories.put(tempBoxItem.key, tempBoxItem.value);
}
} else {
await histories.put(tempBoxItem.key, tempBoxItem.value);
}
}
await tempBox.close();
}
这段代码会比较本地和远程历史记录的 lastWatchTime(最后观看时间),如果远程记录更新,则用远程记录覆盖本地记录,从而保证播放进度的准确性。
实际使用流程
配置 WebDAV 服务器
要使用 Kazumi 的进度同步功能,首先需要在设置中配置 WebDAV 服务器信息。这些配置项定义在 lib/utils/storage.dart 的 SettingBoxKey 类中:
static const String webDavEnable = 'webDavEnable',
webDavEnableHistory = 'webDavEnableHistory',
webDavEnableCollect = 'webDavEnableCollect',
webDavURL = 'webDavURL',
webDavUsername = 'webDavUsername',
webDavPassword = 'webDavPasswd',
用户需要提供 WebDAV 服务器的 URL、用户名和密码,Kazumi 会将这些信息安全存储在本地。
手动触发同步
除了自动同步外,用户还可以手动触发同步操作。同步功能的入口位于应用的设置页面,用户可以根据需要选择同步播放历史或收藏列表。
相关模块与文件
Kazumi 的进度同步功能涉及多个模块和文件,以下是核心组件的路径:
- WebDAV 客户端实现:lib/utils/webdav.dart
- 本地存储管理:lib/utils/storage.dart
- 历史记录数据模型:lib/modules/history/history_module.dart
- 收藏数据模型:lib/modules/collect/collect_module.dart
这些文件共同构成了 Kazumi 的多设备同步系统,确保用户在不同设备上都能获得一致的观看体验。
总结
Kazumi 通过 WebDAV 协议实现了播放进度的跨设备同步,解决了用户在多设备间切换时的播放进度接续问题。核心实现包括 WebDAV 客户端、数据同步逻辑和冲突解决策略,确保了数据的安全性和一致性。
通过本文的介绍,你已经了解了 Kazumi 进度同步功能的工作原理和实现细节。如果你对某个具体模块感兴趣,可以查看相应的源代码文件,深入了解其实现。
如果你在使用同步功能时遇到问题,可以参考项目的 README.md 或提交 issue 寻求帮助。Kazumi 作为一个开源项目,欢迎社区贡献代码和提出改进建议,共同完善这一功能。
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0193- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
awesome-zig一个关于 Zig 优秀库及资源的协作列表。Makefile00