Rename project to JAMS (Just A simple intelligent Media Server), replace lms- prefix with jams- throughout
This commit is contained in:
+46
-44
@@ -1,4 +1,6 @@
|
||||
# LLM 媒体服务器 — 架构设计文档
|
||||
# JAMS — 架构设计文档
|
||||
|
||||
> **JAMS**: Just A simple intelligent Media Server
|
||||
|
||||
> 参考 Jellyfin 核心架构模式,以 Rust 实现。
|
||||
|
||||
@@ -7,17 +9,17 @@
|
||||
## 1. Cargo Workspace 结构
|
||||
|
||||
```
|
||||
lms/ ← workspace 根目录
|
||||
jams/ ← workspace 根目录
|
||||
├── Cargo.toml ← workspace 成员声明
|
||||
├── crates/
|
||||
│ ├── lms-server/ ← 二进制入口,Axum 路由,依赖注入组装
|
||||
│ ├── lms-core/ ← 共享 Trait、领域类型、错误类型
|
||||
│ ├── lms-library/ ← LibraryManager、FileWatcher、MediaResolver
|
||||
│ ├── lms-metadata/ ← MetadataRouter 及各 Provider 实现
|
||||
│ ├── lms-llm/ ← LlmRouter 及各 LLM Provider 实现
|
||||
│ ├── lms-media/ ← ffmpeg 封装、MediaProbe、缩略图提取
|
||||
│ ├── lms-stream/ ← StreamBuilder、直接播放、HLS 处理
|
||||
│ └── lms-db/ ← SQLite/sqlx、迁移、Repository 实现
|
||||
│ ├── jams-server/ ← 二进制入口,Axum 路由,依赖注入组装
|
||||
│ ├── jams-core/ ← 共享 Trait、领域类型、错误类型
|
||||
│ ├── jams-library/ ← LibraryManager、FileWatcher、MediaResolver
|
||||
│ ├── jams-metadata/ ← MetadataRouter 及各 Provider 实现
|
||||
│ ├── jams-llm/ ← LlmRouter 及各 LLM Provider 实现
|
||||
│ ├── jams-media/ ← ffmpeg 封装、MediaProbe、缩略图提取
|
||||
│ ├── jams-stream/ ← StreamBuilder、直接播放、HLS 处理
|
||||
│ └── jams-db/ ← SQLite/sqlx、迁移、Repository 实现
|
||||
├── docs/
|
||||
└── docker/
|
||||
├── Dockerfile
|
||||
@@ -27,27 +29,27 @@ lms/ ← workspace 根目录
|
||||
**依赖方向**(单向,无环):
|
||||
|
||||
```
|
||||
lms-server
|
||||
├── lms-library → lms-core, lms-db
|
||||
├── lms-metadata → lms-core, lms-llm
|
||||
├── lms-llm → lms-core
|
||||
├── lms-media → lms-core
|
||||
├── lms-stream → lms-core, lms-media, lms-db
|
||||
└── lms-db → lms-core
|
||||
jams-server
|
||||
├── jams-library → jams-core, jams-db
|
||||
├── jams-metadata → jams-core, jams-llm
|
||||
├── jams-llm → jams-core
|
||||
├── jams-media → jams-core
|
||||
├── jams-stream → jams-core, jams-media, jams-db
|
||||
└── jams-db → jams-core
|
||||
```
|
||||
|
||||
`lms-core` 不依赖任何其他 crate,所有 Trait 定义在此。
|
||||
`jams-core` 不依赖任何其他 crate,所有 Trait 定义在此。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心 Trait 定义(lms-core)
|
||||
## 2. 核心 Trait 定义(jams-core)
|
||||
|
||||
参考 Jellyfin 的 `IMetadataProvider` 层次,用 Rust Trait 对象实现同等抽象。
|
||||
|
||||
### 2.1 元数据 Provider
|
||||
|
||||
```rust
|
||||
// crates/lms-core/src/providers/metadata.rs
|
||||
// crates/jams-core/src/providers/metadata.rs
|
||||
|
||||
#[async_trait]
|
||||
pub trait MetadataProvider: Send + Sync {
|
||||
@@ -89,7 +91,7 @@ pub struct MetadataResult {
|
||||
### 2.2 LLM Provider
|
||||
|
||||
```rust
|
||||
// crates/lms-core/src/providers/llm.rs
|
||||
// crates/jams-core/src/providers/llm.rs
|
||||
|
||||
#[async_trait]
|
||||
pub trait LlmProvider: Send + Sync {
|
||||
@@ -113,7 +115,7 @@ pub struct LlmOptions {
|
||||
参考 Jellyfin `BaseItem`,但用 Rust enum 替代继承层次。
|
||||
|
||||
```rust
|
||||
// crates/lms-core/src/domain/item.rs
|
||||
// crates/jams-core/src/domain/item.rs
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MediaItem {
|
||||
@@ -148,7 +150,7 @@ pub struct ClassificationResult {
|
||||
### 2.4 流媒体能力描述(参考 Jellyfin DeviceProfile)
|
||||
|
||||
```rust
|
||||
// crates/lms-core/src/stream/profile.rs
|
||||
// crates/jams-core/src/stream/profile.rs
|
||||
|
||||
pub struct ClientCapabilities {
|
||||
pub supported_containers: Vec<String>, // ["mp4", "mkv", "webm"]
|
||||
@@ -224,7 +226,7 @@ pub struct ClientCapabilities {
|
||||
## 4. MediaResolver — 文件名解析(参考 Emby.Naming)
|
||||
|
||||
```rust
|
||||
// crates/lms-library/src/resolver.rs
|
||||
// crates/jams-library/src/resolver.rs
|
||||
|
||||
pub struct MediaResolver {
|
||||
episode_patterns: Vec<Regex>, // 编译期初始化,启动时只编译一次
|
||||
@@ -264,7 +266,7 @@ const EPISODE_PATTERNS: &[&str] = &[
|
||||
## 5. MetadataRouter — 优先级路由(参考 Jellyfin ProviderManager)
|
||||
|
||||
```rust
|
||||
// crates/lms-metadata/src/router.rs
|
||||
// crates/jams-metadata/src/router.rs
|
||||
|
||||
pub struct MetadataRouter {
|
||||
providers: Vec<Box<dyn MetadataProvider>>, // 按 priority() 排序
|
||||
@@ -294,7 +296,7 @@ impl MetadataRouter {
|
||||
}
|
||||
}
|
||||
|
||||
// Provider 注册(lms-server 组装)
|
||||
// Provider 注册(jams-server 组装)
|
||||
fn build_metadata_router(cfg: &Config) -> MetadataRouter {
|
||||
let mut providers: Vec<Box<dyn MetadataProvider>> = vec![
|
||||
Box::new(TmdbProvider::new(&cfg.metadata.tmdb_api_key)), // priority: 10
|
||||
@@ -319,7 +321,7 @@ fn build_metadata_router(cfg: &Config) -> MetadataRouter {
|
||||
## 6. LlmRouter — 多 Provider 路由(含降级)
|
||||
|
||||
```rust
|
||||
// crates/lms-llm/src/router.rs
|
||||
// crates/jams-llm/src/router.rs
|
||||
|
||||
pub struct LlmRouter {
|
||||
primary: Box<dyn LlmProvider>,
|
||||
@@ -348,7 +350,7 @@ impl LlmRouter {
|
||||
}
|
||||
|
||||
// Provider 实现列表
|
||||
// crates/lms-llm/src/providers/
|
||||
// crates/jams-llm/src/providers/
|
||||
// ollama.rs → GET http://localhost:11434/api/generate
|
||||
// claude.rs → POST https://api.anthropic.com/v1/messages
|
||||
// openai.rs → POST https://api.openai.com/v1/chat/completions
|
||||
@@ -359,7 +361,7 @@ impl LlmRouter {
|
||||
## 7. StreamBuilder — 流媒体决策树(参考 Jellyfin StreamBuilder.cs)
|
||||
|
||||
```rust
|
||||
// crates/lms-stream/src/builder.rs
|
||||
// crates/jams-stream/src/builder.rs
|
||||
|
||||
pub enum StreamPlan {
|
||||
DirectPlay { path: PathBuf },
|
||||
@@ -441,7 +443,7 @@ async fn stream_handler(
|
||||
|
||||
---
|
||||
|
||||
## 8. 数据库 Schema(lms-db)
|
||||
## 8. 数据库 Schema(jams-db)
|
||||
|
||||
参考 Jellyfin 从单体 `BaseItemRepository` 演进为服务化 Repository 的方向,我们从一开始就按职责拆分。
|
||||
|
||||
@@ -614,11 +616,11 @@ base_url = "https://api.openai.com/v1" # 支持自定义端点
|
||||
model = "gpt-4o"
|
||||
|
||||
[streaming]
|
||||
transcode_dir = "/tmp/lms-transcode"
|
||||
transcode_dir = "/tmp/jams-transcode"
|
||||
max_concurrent_jobs = 2
|
||||
|
||||
[db]
|
||||
path = "/data/lms.db"
|
||||
path = "/data/jams.db"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -637,10 +639,10 @@ services:
|
||||
volumes:
|
||||
- ./config:/config # TOML 配置 + SQLite DB
|
||||
- /your/media:/media:ro # 媒体目录(只读挂载)
|
||||
- /tmp/lms-transcode:/transcode # 转码临时目录(推荐高速盘)
|
||||
- /tmp/jams-transcode:/transcode # 转码临时目录(推荐高速盘)
|
||||
environment:
|
||||
- LMS_DB_PATH=/config/lms.db
|
||||
- LMS_CONFIG=/config/lms.toml
|
||||
- JAMS_DB_PATH=/config/jams.db
|
||||
- JAMS_CONFIG=/config/jams.toml
|
||||
restart: unless-stopped
|
||||
|
||||
ollama:
|
||||
@@ -667,13 +669,13 @@ volumes:
|
||||
FROM rust:1.82-slim AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN cargo build --release --bin lms-server
|
||||
RUN cargo build --release --bin jams-server
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
RUN apt-get update && apt-get install -y ffmpeg ca-certificates && rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=builder /app/target/release/lms-server /usr/local/bin/lms-server
|
||||
COPY --from=builder /app/target/release/jams-server /usr/local/bin/jams-server
|
||||
EXPOSE 3000
|
||||
ENTRYPOINT ["lms-server"]
|
||||
ENTRYPOINT ["jams-server"]
|
||||
```
|
||||
|
||||
---
|
||||
@@ -681,14 +683,14 @@ ENTRYPOINT ["lms-server"]
|
||||
## 12. 各 crate 关键依赖
|
||||
|
||||
```toml
|
||||
# lms-server
|
||||
# jams-server
|
||||
axum = "0.7"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tower-http = { version = "0.5", features = ["cors", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
|
||||
# lms-core
|
||||
# jams-core
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
@@ -696,17 +698,17 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
async-trait = "0.1"
|
||||
thiserror = "1"
|
||||
|
||||
# lms-library
|
||||
# jams-library
|
||||
notify = "6" # 跨平台文件系统监听(inotify on Linux)
|
||||
regex = "1"
|
||||
|
||||
# lms-db
|
||||
# jams-db
|
||||
sqlx = { version = "0.7", features = ["sqlite", "runtime-tokio", "migrate", "uuid", "chrono"] }
|
||||
|
||||
# lms-llm / lms-metadata
|
||||
# jams-llm / jams-metadata
|
||||
reqwest = { version = "0.12", features = ["json"] }
|
||||
|
||||
# lms-media
|
||||
# jams-media
|
||||
tokio-process = "1" # 异步子进程(ffmpeg/ffprobe)
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user