# SkyReels Rust SDK

一个功能全面的 Rust SDK，用于与 SkyReels AI 视频生成 API 进行交互。

## 特性

- 🎬 **文生视频生成**：通过文本提示生成视频
- 🔄 **异步/等待**：基于 Tokio 构建的高效异步操作
- 🛡️ **类型安全**：利用 Rust 类型系统进行强类型检查
- 🎯 **错误处理**：完善的错误类型和重试逻辑
- 🔧 **可配置**：支持自定义基础 URL 和 API 密钥
- 📝 **文档完善**：提供丰富的文档和示例

## 环境配置

### 使用 .env 文件（推荐用于示例）

示例使用 `dotenv` 从 `.env` 文件加载环境变量：

1. 复制示例环境文件：
   ```bash
   cp .env.example .env
   ```

2. 编辑 `.env` 并添加你的 API 密钥：
   ```env
   SKYREELS_API_KEY=your_actual_api_key_here
   ```

3. 运行示例（它们会自动加载 .env 文件）：
   ```bash
   cargo run --example basic_usage
   ```

### 手动配置环境变量

或者，你可以直接设置环境变量：

```bash
export SKYREELS_API_KEY="your_api_key_here"
cargo run --example basic_usage
```

## 安装

将以下内容添加到你的 `Cargo.toml`：

```toml
[dependencies]
skyreels-sdk = "0.1.0"
tokio = { version = "1", features = ["full"] }
```

## 快速开始

```rust
use skyreels_sdk::{AspectRatio, Mode, SkyReelsClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 使用你的 API 密钥创建客户端
    let client = SkyReelsClient::new("your_api_key");

    // 提交文生视频任务
    let task_id = client.text2video()
        .submit_request("海面上美丽的日落")
        .duration(5)
        .aspect_ratio(AspectRatio::Wide16x9)
        .sound(true)
        .mode(Mode::Std)
        .build();

    // 注意：你需要提交请求（这里只是构建请求）
    // 在实际场景中，你需要使用 submit 方法

    // 查询任务状态
    let status = client.text2video()
        .get_task(&task_id)
        .await?;

    println!("任务状态: {}", status.get_status());

    Ok(())
}
```

## 示例

SDK 包含多个示例来展示各种功能：

### 环境测试

首先，测试你的环境配置：

```bash
cargo run --example test_env
```

这将验证你的 `.env` 文件是否正确配置。

### 基础用法

```bash
cargo run --example basic_usage
```

演示：
- 创建客户端
- 提交文生视频任务
- 查询任务状态
- 不同的宽高比和模式

### 完整工作流

```bash
cargo run --example complete_workflow
```

演示：
- 提交任务
- 轮询等待完成
- 提取视频数据
- 错误处理

### 错误处理

```bash
cargo run --example error_handling
```

演示：
- 不同的错误类型
- 可重试错误的重试逻辑
- 状态码处理
- 错误处理最佳实践

### 环境配置测试

```bash
cargo run --example test_env
```

验证环境变量是否从 `.env` 文件正确加载。

### 自定义客户端配置

```bash
cargo run --example custom_client
```

演示：
- 自定义基础 URL
- 动态更新 API 密钥
- 多客户端用于不同环境
- 代理配置

## API 文档

### 客户端配置

```rust
// 默认客户端
let client = SkyReelsClient::new("your_api_key");

// 自定义基础 URL
let client = SkyReelsClient::with_base_url(
    "your_api_key",
    "https://custom-gateway.example.com"
);

// 动态更新 API 密钥
client.set_api_key("new_api_key").await;

// 动态更新基础 URL
client.set_base_url("https://new-gateway.example.com").await;
```

### 文生视频生成

```rust
use skyreels_sdk::{AspectRatio, Mode};

// 提交任务
let task_id = client.text2video()
    .submit_request("你的提示词")
    .duration(5)           // 3-15 秒（默认：5）
    .aspect_ratio(AspectRatio::Wide16x9)  // 16:9, 4:3, 1:1, 9:16, 3:4
    .sound(true)           // 包含音效
    .mode(Mode::Std)       // Fast, Std, Pro
    .build();
```

### 任务状态查询

```rust
let response = client.text2video()
    .get_task(&task_id)
    .await?;

match response.get_status() {
    TaskStatus::Success => {
        if let Some(video) = response.get_video_data() {
            println!("视频 URL: {}", video.video_url);
            println!("时长: {} 秒", video.duration);
            println!("分辨率: {}", video.resolution);
        }
    }
    TaskStatus::Failed => {
        eprintln!("任务失败: {}", response.msg);
    }
    _ => {
        println!("任务正在处理中...");
    }
}
```

### 等待完成

```rust
let response = client.text2video()
    .wait_for_completion(&task_id, 5, 120)  // 每 5 秒轮询，最多 120 次
    .await?;

if let Some(video) = response.get_video_data() {
    println!("视频就绪: {}", video.video_url);
}
```

## 错误处理

SDK 提供完善的错误处理：

```rust
use skyreels_sdk::Error;

match client.text2video().get_task(&task_id).await {
    Ok(response) => { /* 处理成功 */ }
    Err(Error::NetworkError(e)) => {
        eprintln!("网络错误: {}", e);
    }
    Err(Error::ApiError { status, message }) => {
        eprintln!("API 错误 ({}): {}", status, message);
    }
    Err(Error::TaskNotFound(task_id)) => {
        eprintln!("任务未找到: {}", task_id);
    }
    Err(e) => {
        eprintln!("错误: {}", e);
    }
}
```

### 重试逻辑

```rust
let mut attempts = 0;
let max_retries = 3;

loop {
    match client.text2video().get_task(&task_id).await {
        Ok(response) => break Ok(response),
        Err(e) if !e.is_retryable() || attempts >= max_retries => break Err(e),
        Err(_) => {
            attempts += 1;
            tokio::time::sleep(tokio::time::Duration::from_secs(2_u64.pow(attempts))).await;
        }
    }
}
```

## API 参考

### 宽高比

- `Wide16x9` - 16:9（横向/宽屏，默认）
- `Standard4x3` - 4:3（标准横向）
- `Square1x1` - 1:1（方形）
- `Portrait9x16` - 9:16（竖向/移动端）
- `Standard3x4` - 3:4（标准竖向）

### 模式

- `Fast` - 快速生成（即将推出）
- `Std` - 标准模式（默认，当前支持）
- `Pro` - 专业模式（即将推出）

### 任务状态

- `Submitted` - 任务已提交
- `Pending` - 任务等待中
- `Running` - 任务正在处理
- `Success` - 任务成功完成
- `Failed` - 任务失败
- `Unknown` - 未知状态

## 错误类型

- `NetworkError` - 网络或 HTTP 错误
- `ApiError` - API 错误及状态码
- `InvalidParameter` - 提供的参数无效
- `MissingApiKey` - 未配置 API 密钥
- `SubmissionFailed` - 任务提交失败
- `QueryFailed` - 任务查询失败
- `ResponseParseError` - 响应解析失败
- `TaskNotFound` - 任务未找到或 ID 无效
- `RateLimitExceeded` - 超过速率限制
- `AuthenticationFailed` - 认证失败

## 贡献

欢迎贡献！请随时提交 Pull Request。

## 许可证

本项目采用 Apache License 2.0 许可 - 详见 LICENSE 文件。

## 支持

- 📧 邮箱: support@skyreels.ai
- 🌐 网站: https://skyreels.ai
- 📚 文档: https://docs.skyreels.ai

## 致谢

构建于以下项目：
- [reqwest](https://github.com/seanmonstar/reqwest) - HTTP 请求
- [tokio](https://tokio.rs/) - 异步运行时
- [serde](https://serde.rs/) - 序列化
- [thiserror](https://github.com/dtolnay/thiserror) - 错误处理
