HLS VOD Backend
把 `.m3u8` 当作要拼装的流而不是要保存的文本文件:解析清单、选码率、分片并发(分片级重试)、AES-128 解密、字节范围。
dev.turbodl:turbo-plugin-hls:0.4.1.0
项目自带两个插件;事实上其它东西也都是插件 —— Kotlin 加载器、HTTP 后端、HLS 适配器。内核本身不认识任何协议。
把 `.m3u8` 当作要拼装的流而不是要保存的文本文件:解析清单、选码率、分片并发(分片级重试)、AES-128 解密、字节范围。
dev.turbodl:turbo-plugin-hls:0.4.1.0
加载用 JavaScript 写的 TurboDL 插件。每个脚本一个 QuickJS runtime 与 context、一套稳定的 `host`/`plugin` ABI,以及一套「绝不在脚本还在执行时关掉 runtime」的加载/卸载流程。
dev.turbodl:turbo-plugin-js:0.4.1.0
把分享链接变成可下载请求:微博(最高可用清晰度 MP4 + 图集)、小红书(无水印视频 + 原图)、Pixiv(每页 `urls.original`)。注册一个 `LinkParser` 与每个平台一条 `ProtocolClaim` — 引擎对这三个站点一无所知。
dev.turbodl:turbo-plugin-parser:0.4.1.0
两个官方插件一共声明了 5 项能力。它们不做的事情都列在旁边 —— 当另一种做法是产出一个损坏的文件时,「拒绝」本身就是功能。
声明的能力
从各插件的 turbodl-plugin.json 里读出来的。
明确拒绝
不支持的流会响亮地失败,而不是产出一个看起来正常的文件。
插件在清单里声明一个分类。分类只说明它能接到哪里,不说明别的。
turbodl-plugin.json · category
分类就是这个运行时的全部授权依据:它决定插件可以注册哪些扩展点。
插件就是一个实现了某个接口的普通类。第三方插件通过 GitHub topic + 清单被发现 —— 没有需要注册的中心仓库。
class MyPlugin : Plugin {
override val id = "parser.example"
override fun onLoad(context: PluginContext) {
context.registerExtension(ExtensionPoints.LINK_PARSER, LinkParser { input ->
input.takeIf { it.startsWith("example://") }
?.let { listOf(DownloadRequest(url = it, destination = File("out.bin"))) }
})
}
}turbodl-plugin.json
{
"manifestVersion": "1.0",
"id": "parser.example",
"name": "Example parser",
"description": "Turns example:// links into download requests.",
"version": "0.1.0",
"author": "you",
"homepage": "https://github.com/you/turbodl-plugin-example",
"license": "MIT",
"category": "turbodl-parser",
"capabilities": [
"dev.turbodl.cap.parser"
],
"protocols": [
"example"
],
"turbodl": {
"apiMajor": 1,
"requiredApiVersion": "1.0.0"
},
"entry": {
"language": "kotlin",
"pluginClass": "com.example.ExamplePlugin"
},
"extensionPoints": [
"turbo.linkParser"
]
}六个必填字段、一个分类、一个入口。参考页列了每个字段与允许的取值。