视频播放进度同步: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 作为一个开源项目,欢迎社区贡献代码和提出改进建议,共同完善这一功能。
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin08
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00