# mstf-kit

[English](./README.en.md) | 简体中文

一个现代化的 JavaScript/TypeScript 工具库，提供了丰富的常用工具函数。

## ✨ 特性

- 📦 支持 Tree Shaking
- 🔧 TypeScript 支持
- 📚 完整的类型定义
- 🎯 模块化设计
- 💪 全面的测试覆盖
- 📝 详细的文档
- 🔒 代码混淆保护

## 📦 安装

```bash
npm install mstf-kit
# 或
yarn add mstf-kit
# 或
pnpm add mstf-kit
```

## 🚀 使用方法

```typescript
// 导入所需的工具函数
import { formatDate, isEmail } from 'mstf-kit';

// 使用日期格式化
const date = formatDate(new Date(), 'YYYY-MM-DD');
console.log(date); // 2024-03-10

// 验证邮箱
const isValidEmail = isEmail('example@email.com');
console.log(isValidEmail); // true
```

### 按需导入

为了减小打包体积，推荐使用 tree-shaking 按需导入具体的工具函数：

```typescript
// 只导入需要的函数
import { capitalize, truncate } from 'mstf-kit';
import { formatDate } from 'mstf-kit';
import { createLottiePlayer } from 'mstf-kit';

// 不要这样导入整个库
// import * as mstfKit from 'mstf-kit'; // ❌ 不推荐
```

现代打包工具（如 webpack、rollup、vite）会自动进行 tree-shaking，只打包您实际使用的代码。

## 📚 API 文档

### 🔤 字符串工具 (String Utils)

字符串处理相关的工具函数。

- `capitalize(str: string): string` - 首字母大写
- `camelCase(str: string): string` - 转换为驼峰命名
- `truncate(str: string, length: number): string` - 截断字符串

### 🔢 数字工具 (Number Utils)

数字处理和计算相关的工具函数。

- `formatNumber(num: number, locale?: string): string` - 数字格式化
- `round(num: number, decimals?: number): number` - 四舍五入
- `clamp(num: number, min: number, max: number): number` - 限制数字范围
- `random(min: number, max: number, isInteger?: boolean): number` - 生成随机数
- `percentage(value: number, total: number, decimals?: number): number` - 计算百分比

### 📋 数组工具 (Array Utils)

数组操作和处理的工具函数。

- `unique<T>(arr: T[]): T[]` - 数组去重
- `groupBy<T>(arr: T[], key: string | ((item: T) => string)): Record<string, T[]>` - 数组分组
- `flatten<T>(arr: any[], depth?: number): T[]` - 数组扁平化
- `sample<T>(arr: T[], count?: number): T | T[]` - 随机采样
- `shuffle<T>(arr: T[]): T[]` - 数组乱序
- `closest(arr: number[], target: number): number` - 查找最接近的值

### 📦 对象工具 (Object Utils)

对象操作和处理的工具函数。

- `deepClone<T>(obj: T): T` - 深拷贝
- `get(obj: any, path: string | string[], defaultValue?: any): any` - 获取嵌套属性
- `set(obj: any, path: string | string[], value: any): void` - 设置嵌套属性
- `pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>` - 选择属性
- `omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K>` - 排除属性
- `merge<T>(...objects: T[]): T` - 对象合并

### 📅 日期工具 (Date Utils)

日期和时间处理的工具函数。

- `formatDate(date: Date | number | string, format?: string): string` - 日期格式化
- `getRelativeTime(date: Date | number | string, now?: Date): string` - 相对时间
- `getDateRange(start: Date | number | string, end: Date | number | string): Date[]` - 日期范围
- `addTime(date: Date | number | string, amount: number, unit: string): Date` - 添加时间
- `isSameDay(date1: Date | number | string, date2: Date | number | string): boolean` - 判断同一天

### ✅ 验证工具 (Validation Utils)

数据验证相关的工具函数。

- `isEmail(email: string): boolean` - 验证邮箱
- `isChinesePhone(phone: string): boolean` - 验证手机号（中国大陆）
- `isChineseIdCard(idCard: string): boolean` - 验证身份证号（中国大陆）
- `isUrl(url: string): boolean` - 验证URL
- `isIPv4(ip: string): boolean` - 验证IPv4地址
- `validatePassword(password: string, options?: object): boolean` - 验证密码强度
- `isSafeString(str: string): boolean` - 验证XSS安全

### 🛠️ 工具类 (Utils)


#### 📝 Logger 日志工具

统一的日志工具类，提供可配置的日志输出功能。支持多种日志级别、时间戳、自定义前缀等特性。

```typescript
import { createLogger, LogLevel } from 'mstf-kit';

// 创建 Logger
const logger = createLogger({
  enabled: true,
  prefix: '[MyApp]',
  level: LogLevel.DEBUG,
  showTimestamp: true
});

// 使用日志
logger.log('应用启动');
logger.warn('这是一条警告');
logger.error('这是一条错误');

// 创建子 Logger
const authLogger = logger.createChild('Auth');
authLogger.log('用户登录'); // [MyApp:Auth] 用户登录
```

**📖 [查看 Logger 完整文档](./docs/logger.md)**

### 🎵 音频处理 (Audio)

#### 非流式音频处理 (audioNonStream)

处理非流式接口返回的音频数据，支持多种数据格式（Base64、Blob、ArrayBuffer、File）和灵活的字段路径提取。

```typescript
import { processNonStreamAudio } from 'mstf-kit';

// 处理嵌套字段的 Base64 数据
const response = {
  msg: 'success',
  code: 200,
  data: {
    audio: 'UklGRiQAAABXQVZFZm10...' // Base64音频数据
  }
};

const result = await processNonStreamAudio(response, {
  audioField: 'data.audio',  // 指定音频数据的路径
  dataType: 'base64',        // 指定数据类型
  mimeType: 'audio/wav',     // 指定MIME类型
  autoPlay: true             // 自动播放
});

console.log('音频URL:', result.url);
console.log('音频大小:', result.size);
```

**📖 [查看非流式音频处理完整文档](./docs/audio-nonstream.md)**

#### 流式音频处理器 V2 (audioStreamV2)

新版流式音频处理器，支持有头部和无头部两种流式音频格式，提供更灵活的配置。

```typescript
import { processStreamAudioV2 } from 'mstf-kit';

// 处理流式音频
const response = await fetch('/api/audio/stream');
const reader = response.body.getReader();

const { pause, resume, abort, isPlaying } = await processStreamAudioV2(reader, {
  autoPlay: true,
  dataFormat: 'auto',          // 自动检测格式：'with-header' | 'without-header' | 'auto'
  audioField: 'data.audio',
  debug: true,
  
  onStart: () => console.log('开始播放'),
  onEnded: () => console.log('播放结束'),
  onAudioData: (blob) => console.log('收到音频块:', blob.size)
});

// 控制播放
pauseButton.onclick = () => pause();
playButton.onclick = () => resume();
```

**主要特性：**
- 支持有头部格式（每个块都有完整头部）
- 支持无头部格式（只有第一个块有头部）
- 自动格式检测
- 集成 Logger 日志系统
- 完整的 TypeScript 类型支持

**📖 [查看流式音频处理器 V2 完整文档](./docs/audio-stream-v2.md)**

#### 音频流处理 (audioStream)

音频流处理工具，用于处理音频数据流，支持ArrayBuffer和流式数据，并提供自动播放功能。

```typescript
import { 
  createAudioStreamHandler, 
  handleAudioBuffer, 
  createAudioHandlers 
} from 'mstf-kit';

// 示例1: 处理ArrayBuffer响应
const response = await axios.post('/api/voice/synthesize', {
  voice_id: 'my-voice',
  text: '你好，世界！'
}, {
  responseType: 'arraybuffer',
  headers: { Accept: 'audio/mp3' }
});

// 方式1: 直接处理
const { blob, url, handler } = await handleAudioBuffer(response, {
  mimeType: 'audio/mp3',
  autoPlay: true,
  logLevel: 'debug'
});

// 示例2: 处理流式数据
// 创建处理器
const audioHandler = createAudioStreamHandler({
  mimeType: 'audio/mp3',
  logLevel: 'debug'
});

// 示例3: 最简单的方式 (一步到位)
const { config, handler } = createAudioHandlers(
  {
    responseType: 'arraybuffer',
    headers: { Accept: 'audio/mp3' }
  },
  {
    mimeType: 'audio/mp3',
    autoPlayOnComplete: true,
    logLevel: 'debug'
  }
);

// 使用增强的配置发送请求
const response = await axios.post('/api/voice/synthesize', data, config);
```

#### 轻量级音频请求处理 (audioRequest)

轻量级音频处理工具，专注于处理流式和非流式音频数据，无需额外依赖，支持各种响应格式。

```typescript
import { 
  processStreamResponse, 
  processArrayBuffer, 
  processBlob,
  processBase64Audio,
  createBase64StreamProcessor
} from 'mstf-kit';

// 示例1: 使用fetch和getReader处理流式响应
const response = await fetch('https://api.example.com/audio/stream', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ text: '要合成的文本' })
});

// 获取响应流的Reader
const reader = response.body.getReader();
// 处理流式音频数据
const { pause, resume, abort, isPlaying, finalBlob } = await processStreamResponse(reader, {
  autoPlay: true,             // 自动播放
  returnBlob: true,           // 返回完整Blob
  audioField: 'data.audio',   // 音频数据在响应中的路径
  onStart: () => {            // 音频开始播放回调
    console.log('音频开始播放');
    playButton.classList.add('playing');
  },
  onEnded: () => {            // 音频播放结束回调
    console.log('音频播放结束');
    playButton.classList.remove('playing');
    statusElement.textContent = '播放完成';
  },
  onAudioData: (blob) => {     // 接收到新音频块时的回调
    console.log('收到音频数据块:', blob.size);
  },
  onComplete: (blob) => {      // 处理完成回调
    if (blob) {
      console.log('完整音频大小:', blob.size);
    }
  }
});

// 播放控制
pauseButton.addEventListener('click', () => {
  pause();
  playButton.classList.remove('playing');
});

playButton.addEventListener('click', () => {
  resume();
  playButton.classList.add('playing');
});

// 监控播放状态
setInterval(() => {
  const playing = isPlaying();
  statusElement.textContent = playing ? '播放中' : '已暂停';
}, 100);

// 中止处理
cancelButton.addEventListener('click', () => {
  abort();
});

// 获取完整音频
if (finalBlob) {
  const blob = await finalBlob;
  const url = URL.createObjectURL(blob);
  audio.src = url;
}
```

支持的选项:

```typescript
// 音频处理选项
{
  autoPlay?: boolean;         // 是否自动播放
  returnBlob?: boolean;       // 是否返回完整Blob
  mimeType?: string;          // MIME类型，默认为'audio/wav'
  audioField?: string;        // 音频数据字段路径，如'data.audio'
  onAudioData?: (audioBlob: Blob) => void;      // 接收到音频数据回调
  onError?: (error: Error) => void;             // 错误回调
  onComplete?: (blob?: Blob) => void;           // 完成回调
  onStart?: () => void;                  // 音频开始播放回调
  onEnded?: () => void;                  // 音频播放结束回调
}
```

##### Axios支持

使用 Axios 处理流式和非流式音频请求：

```typescript
import axios from 'axios';
import { createAxiosAudioOptions } from 'mstf-kit';

// 流式音频请求 - 创建配置
const { axiosConfig, pause, resume, abort, isPlaying, finalBlob } = createAxiosAudioOptions({
  autoPlay: true,              // 自动播放
  returnBlob: true,            // 返回完整Blob
  audioField: 'data.audio',    // 音频数据在响应JSON中的路径
  mimeType: 'audio/wav',       // 音频MIME类型
  onStart: () => {             // 音频开始播放回调
    console.log('音频开始播放');
    playButton.disabled = false;
  },
  onAudioData: (blob) => {       // 接收到音频块的回调
    console.log('收到音频数据块:', blob.size);
  }
});

// 发送请求
const response = await axios.post(
  'https://api.example.com/audio/stream',
  { text: '要合成的文本' },
  axiosConfig
);

// 控制播放
const togglePlay = () => {
  if (isPlaying()) {
    pause();
    playButton.textContent = '播放';
  } else {
    resume();
    playButton.textContent = '暂停';
  }
};

playButton.addEventListener('click', togglePlay);
```

##### 自定义数据格式

可以处理多种服务器返回的数据格式：

1. **标准格式**：`data: {"audio":"base64数据","is_last":false}`
2. **自定义路径**：通过 `audioField` 指定音频数据的路径

```typescript
// 标准格式处理
const { pause, resume, abort, isPlaying } = await processStreamResponse(reader, {
  autoPlay: true
});

// 自定义路径处理
const { pause, resume, abort, isPlaying } = await processStreamResponse(reader, {
  autoPlay: true,
  audioField: 'result.data.audioContent' // 指定自定义路径
});

// Axios处理自定义格式
const { axiosConfig, pause, resume, abort, isPlaying } = createAxiosAudioOptions({
  autoPlay: true,
  audioField: 'response.voice.content'
});
```

智能数据提取：如果未指定 `audioField`，将自动尝试从以下位置提取音频数据：

- 直接以字符串形式提供的数据
- 对象的 `audio` 属性
- 嵌套在 `data.audio` 中的数据

##### 停止/中止处理

支持通过AbortController中止处理过程：

```typescript
// 创建AbortController
const controller = new AbortController();
const signal = controller.signal;

// 方法1: 通过配置传入
const { config, handler } = createAudioHandlers(
  { /* axios配置 */ },
  { 
    abortSignal: signal,
    // 其他选项...
  }
);

// 方法2: 直接设置
audioHandler.setAbortSignal(signal);

// 方法3: 直接调用abort方法
audioHandler.abort();

// 在需要中止时：
controller.abort(); // 这将触发中止处理
```

##### 控制播放

```typescript
// 暂停播放
handler.pause();

// 恢复播放
handler.resume();

// 停止播放
handler.stop();

// 设置音量 (0-1)
handler.setVolume(0.5);

// 释放资源
handler.release();
```

##### 配置选项

`AudioStreamOptions` 支持以下选项：

```typescript
{
  // 日志级别: 'none' | 'error' | 'warn' | 'info' | 'debug'
  logLevel?: LogLevel;
  
  // 是否自动播放
  autoPlay?: boolean;
  
  // 自定义的MIME类型
  mimeType?: string;
  
  // 是否循环播放
  loop?: boolean;
  
  // 初始音量 (0-1)
  volume?: number;
  
  // 播放完成回调
  onEnded?: () => void;
  
  // 播放错误回调
  onError?: (error: Error) => void;
  
  // 播放开始回调
  onPlay?: () => void;
  
  // 播放进度回调
  onProgress?: (currentTime: number, duration: number) => void;
  
  // 数据加载回调
  onDataLoaded?: (blob: Blob) => void;
  
  // 处理被中止回调
  onAborted?: () => void;
}
```

`DownloadProgressConfig` 支持以下选项：

```typescript
{
  // 是否需要解析处理
  needParse?: boolean;
  
  // 音频数据路径，如 "audio.b"
  audioPath?: string;
  
  // MIME类型
  mimeType?: string;
  
  // 是否在接收到第一块数据时自动播放
  autoPlayOnFirstChunk?: boolean;
  
  // 是否在下载完成时自动播放
  autoPlayOnComplete?: boolean;
  
  // 用于停止处理的AbortSignal
  abortSignal?: AbortSignal;
}
```

### 🔊 音频播放器

`mstf-kit` 提供了功能强大的音频播放工具，支持背景播放和页面渲染两种模式：

#### 背景播放模式

```typescript
import { createAudioPlayer, playAudio } from 'mstf-kit';

// 简易播放方式
const audioBlob = new Blob([...]); // 音频数据
const player = await playAudio(audioBlob, {
  volume: 0.8,
  loop: true
});

// 或使用完整API
const backgroundPlayer = createAudioPlayer();
await backgroundPlayer.load('https://example.com/audio.mp3');
await backgroundPlayer.play();

// 控制播放
backgroundPlayer.pause();
backgroundPlayer.setVolume(0.5);
backgroundPlayer.seek(30); // 跳转到30秒位置
```

#### 页面渲染模式

```typescript
import { createAudioPlayer, AUDIO_FORMATS } from 'mstf-kit';

// 创建一个带UI界面的播放器
const uiPlayer = createAudioPlayer({
  renderUI: true,           // 启用UI渲染
  container: '#player-box', // 指定容器元素
  theme: 'dark',            // 使用暗色主题
  showVisualization: true,  // 显示音频可视化
  visualizationType: 'bars' // 使用柱状频谱图
});

// 加载音频
await uiPlayer.load(audioBlob);
await uiPlayer.play();

// 播放结束后的回调
uiPlayer.onEnded = () => {
  console.log('播放完成');
};

// 不需要时释放资源
uiPlayer.destroy();
```

#### Vue 集成

与 Vue3 框架无缝集成，支持直接使用 ref 作为容器：

```typescript
import { ref, onMounted, onUnmounted } from 'vue';
import { createAudioPlayer } from 'mstf-kit';

export default {
  setup() {
    // 创建容器引用
    const playerContainer = ref(null);
    let audioPlayer = null;
    
    onMounted(async () => {
      // 创建播放器并使用ref作为容器
      audioPlayer = createAudioPlayer({
        renderUI: true,
        container: playerContainer, // 直接传入ref
        theme: 'dark',
        showVisualization: true
      });
      
      // 加载并播放音频
      await audioPlayer.load('/audio/example.mp3');
      await audioPlayer.play();
    });
    
    // 组件卸载时清理资源
    onUnmounted(() => {
      if (audioPlayer) {
        audioPlayer.destroy();
      }
    });
    
    return { playerContainer };
  }
}
```

#### 可视化类型

播放器支持三种可视化类型：

- `waveform`: 波形图显示
- `bars`: 频谱柱状图
- `circle`: 圆形频谱图

#### 支持的主题

- `default`: 默认主题（浅色）
- `dark`: 暗色主题
- `minimal`: 简约主题（透明背景）


### 🎭 Lottie动画

`mstf-kit` 支持 Lottie 动画的加载、渲染和控制，可以轻松地在您的应用中展示高质量的矢量动画。

#### 基本使用

```typescript
import { createLottiePlayer, playLottie } from 'mstf-kit';

// 快速加载并播放Lottie动画
const player = await playLottie(
  'https://assets.lottiefiles.com/packages/lf20_UJNc2t.json',
  '#animation-container',
  { loop: true, speed: 1.5 }
);

// 或使用完整API
const lottiePlayer = await createLottiePlayer({
  container: '#animation-container',
  renderer: 'canvas', // dotlottie-web 使用 canvas 渲染
  loop: true,
  autoplay: true
});

// 加载动画
await lottiePlayer.load('https://assets.lottiefiles.com/packages/lf20_UJNc2t.json');

// 控制动画
lottiePlayer.pause();
lottiePlayer.setSpeed(2.0);
lottiePlayer.play();
```

#### Vue 集成

与 Vue3 框架无缝集成，支持直接使用 ref 作为容器：

```typescript
import { ref } from 'vue';
import { playLottie } from 'mstf-kit';

export default {
  setup() {
    // 创建容器引用
    const animationContainer = ref(null);
    
    // 加载动画（在onMounted中）
    onMounted(async () => {
      const player = await playLottie(
        'https://assets.lottiefiles.com/packages/lf20_UJNc2t.json',
        animationContainer,
        { loop: true }
      );
    });
    
    return { animationContainer };
  }
}
```

#### 多种库加载模式

支持多种加载方式：

```typescript
// 默认使用内置的 dotlottie-web
const player1 = await createLottiePlayer({
  container: '#animation-container',
  loop: true
});

// 使用自定义外部库
import customLottieLib from 'custom-lottie-lib';
const player2 = await createLottiePlayer({
  container: '#animation-container',
  libOptions: {
    source: 'external',
    externalLib: customLottieLib
  }
});

// 从CDN加载
const player3 = await createLottiePlayer({
  container: '#animation-container',
  libOptions: {
    source: 'cdn',
    cdnURL: 'https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm'
  }
});
```

#### 渲染模式

Lottie播放器默认使用Canvas渲染模式，提供高性能的动画播放体验。

#### 动画控制

播放器支持丰富的控制方法：

```typescript
// 播放控制
player.play();
player.pause();
player.stop();

// 播放速度和方向
player.setSpeed(1.5);  // 1.5倍速
player.setDirection(-1); // 反向播放

// 跳转控制
player.goToFrame(24);  // 跳转到第24帧
player.goToAndPlay(24); // 跳转并播放
player.setSegment(10, 50); // 只播放10-50帧

// 循环控制
player.setLoop(true);  // 无限循环
player.setLoop(3);     // 循环3次

// 动画信息
console.log(`总帧数: ${player.getTotalFrames()}`);
console.log(`当前帧: ${player.getCurrentFrame()}`);
console.log(`时长: ${player.getDuration()}ms`);
console.log(`是否播放中: ${player.isPlaying()}`);

// 资源释放
player.destroy();
```

#### 高级特性

- **小巧高效**: 使用 dotlottie-web 库，体积更小，性能更好
- **多种库来源**: 支持内置库（默认）、CDN加载或外部提供的自定义库
- **Vue框架支持**: 无缝支持Vue3的ref作为容器引用
- **多种来源**: 支持从URL、JSON字符串或对象加载动画
- **动画事件**: 提供丰富的回调函数，可监听动画状态变化
- **响应式**: 通过`resize()`方法支持自适应容器大小


### 🎬 Plyr 播放器 (plyrPlayer)

提供对 Plyr 媒体播放器的封装，支持视频和音频播放，带有丰富的功能和易用的 API。

```typescript
import { createPlyrPlayer, playWithPlyr, createPlaylist } from 'mstf-kit';

// 快速创建简单播放器
const player = await playWithPlyr(
  'https://example.com/video.mp4',
  '#player-container',
  { autoplay: true, muted: true }
);

// 使用完整 API
const advancedPlayer = await createPlyrPlayer({
  container: '#player-container',
  source: {
    type: 'video',
    title: '示例视频',
    sources: [
      {
        src: 'https://example.com/video.mp4',
        type: 'video/mp4'
      }
    ],
    poster: 'https://example.com/poster.jpg'
  },
  controls: ['play', 'progress', 'current-time', 'mute', 'volume', 'settings', 'fullscreen'],
  i18n: {
    play: '播放',
    pause: '暂停',
    mute: '静音',
    volume: '音量'
  }
});

// 访问增强功能
await advancedPlayer.play();
advancedPlayer.addMarker(30, '重要时刻');
const screenshot = advancedPlayer.getCaptureImage();
advancedPlayer.downloadMedia('视频.mp4');
```

#### Vue 集成

无缝支持 Vue3 的 ref 作为容器引用:

```typescript
import { ref, onMounted } from 'vue';
import { createPlyrPlayer } from 'mstf-kit';

export default {
  setup() {
    const playerRef = ref(null);
    let player = null;
    
    onMounted(async () => {
      player = await createPlyrPlayer({
        container: () => playerRef.value, // 使用函数返回 ref 引用的元素
        source: { /* 媒体源配置 */ }
      });
    });
    
    return { playerRef };
  }
}
```

#### 播放列表支持

```typescript
// 创建播放列表
const { player, next, previous, playIndex } = await createPlaylist(
  [
    'https://example.com/video1.mp4',
    'https://example.com/audio1.mp3',
    {
      type: 'video',
      sources: [{ src: 'https://example.com/video2.mp4', type: 'video/mp4' }]
    }
  ],
  '#playlist-container',
  { loop: { active: true } }
);

// 播放控制
next();       // 播放下一个
previous();   // 播放上一个
playIndex(2); // 播放指定索引的媒体
```

#### 主要特性

- **多种加载模式**: 支持 CDN、npm 或外部提供的 Plyr 库
- **增强功能**: 截图捕获、纵横比控制、标记点、画中画等
- **Vue 集成**: 直接支持 Vue ref 作为容器
- **播放列表**: 支持混合媒体类型的播放列表
- **中文本地化**: 内置中文界面文本支持
- **丰富事件**: 提供完整的事件回调系统
- **TypeScript**: 完整的类型定义

#### 支持的配置选项

- **自定义控件**: 可定制控制栏按钮
- **视频比例**: 支持多种纵横比设置
- **播放速度**: 可调节的播放速率
- **字幕**: 支持多语言字幕轨道
- **质量切换**: 支持视频质量选择

##### 强大的增强功能

```typescript
// 修改播放比例
player.changeAspectRatio('16:9');

// 进入画中画模式
await player.enterPictureInPicture();

// 添加时间轴标记
player.addMarker(45, '精彩片段', 'red');

// 截取当前画面
const imageDataUrl = player.getCaptureImage();

// 下载媒体文件
player.downloadMedia('downloaded-video.mp4');

// 自定义快捷键
player.addShortcut('m', () => player.toggleMute());
```

#### 配置选项详解

##### 控制栏按钮 (controls)

可用的控制栏按钮选项:

```typescript
controls: [
  'play-large',  // 大播放按钮
  'play',        // 播放/暂停按钮
  'progress',    // 进度条
  'current-time', // 当前时间
  'duration',    // 总时长
  'mute',        // 静音按钮
  'volume',      // 音量控制
  'captions',    // 字幕按钮
  'settings',    // 设置按钮
  'pip',         // 画中画按钮
  'airplay',     // AirPlay按钮
  'fullscreen',  // 全屏按钮
  'restart',     // 重新播放按钮
  'fast-forward', // 快进按钮
  'rewind'       // 快退按钮
]
```

##### 完整配置选项

```typescript
// 完整的播放器配置选项
{
  // 基本配置
  container: '#player', // 播放器容器(字符串选择器、DOM元素或返回DOM元素的函数)
  source: {             // 媒体源配置
    type: 'video',      // 'video' 或 'audio'
    title: '视频标题',   // 媒体标题
    sources: [          // 媒体源列表
      {
        src: 'https://example.com/video.mp4',
        type: 'video/mp4',
        size: 720       // 清晰度标识(像素高度)
      }
    ],
    poster: 'https://example.com/poster.jpg', // 视频封面图片URL
    tracks: [           // 字幕/章节轨道
      {
        kind: 'captions',
        label: '中文',
        src: 'https://example.com/captions.zh.vtt',
        srclang: 'zh',
        default: true
      }
    ]
  },
  autoplay: false,      // 是否自动播放
  muted: false,         // 是否静音
  loop: { active: false }, // 是否循环播放
  volume: 1.0,          // 默认音量(0-1)
  
  // UI配置
  controls: ['play', 'progress', 'current-time', 'mute', 'volume', 'settings', 'fullscreen'],
  hideControls: true,   // 是否自动隐藏控制栏
  resetOnEnd: false,    // 播放结束后是否重置
  fullscreen: {         // 全屏设置
    enabled: true,      // 是否启用全屏
    fallback: true,     // 如果浏览器不支持原生全屏，是否使用回退方案
    iosNative: true     // 在iOS上使用原生全屏
  },
  ratio: '16:9',        // 视频比例
  storage: {            // 本地存储
    enabled: true,      // 是否启用存储
    key: 'plyr-volume'  // 存储键名
  },
  speed: {              // 播放速度设置
    selected: 1,        // 默认速度
    options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] // 可选速度列表
  },
  quality: {            // 视频质量设置
    default: '720',     // 默认质量
    options: ['1080', '720', '480', '360'] // 可选质量列表(对应sources中的size)
  },
  invertTime: false,    // 是否反转时间显示(显示剩余时间)
  displayDuration: true, // 是否显示总时长
  markers: {            // 时间轴标记点
    enabled: true,      // 是否启用标记点
    points: [           // 标记点列表
      {
        time: 15,       // 标记点时间(秒)
        label: '精彩片段', // 标记点标签
        color: 'red'    // 标记点颜色
      }
    ]
  },
  
  // 本地化文本
  i18n: {
    restart: '重播',
    play: '播放',
    pause: '暂停',
    volume: '音量',
    mute: '静音',
    unmute: '取消静音',
    pip: '画中画',
    normal: '默认',
    settings: '设置',
    speed: '速度',
    quality: '质量',
    loop: '循环',
    start: '开始',
    end: '结束',
    all: '全部',
    reset: '重置',
    disabled: '禁用',
    enabled: '启用',
    advertisement: '广告',
    qualityLabel: {
      1080: '1080p',
      720: '720p',
      480: '480p',
      360: '360p'
    },
    captions: '字幕',
    download: '下载',
    enterFullscreen: '全屏',
    exitFullscreen: '退出全屏'
  },
  
  // 调试设置
  debug: false,         // 是否开启调试模式
  loadSprite: true      // 是否加载SVG雪碧图
}
```

##### createPlyrPlayer 特有选项

```typescript
// 创建Plyr播放器的额外选项
{
  // Plyr库加载选项
  plyrLibOptions: {
    source: 'npm', // 从哪里加载Plyr库: 'cdn'(默认), 'npm', 'local', 'external'
    cdnUrl: 'https://unpkg.com/plyr@3.7.8/dist/plyr.min.js', // 自定义CDN URL
    cssUrl: 'https://unpkg.com/plyr@3.7.8/dist/plyr.css',    // 自定义CSS URL
    externalLib: null // 外部提供的Plyr库实例(当source为'external'时使用)
  },
  initOnLoad: true,     // 是否在加载时立即初始化
  autoCreateCss: true   // 是否自动引入CSS
}
```

#### 增强型播放器API

创建的增强型Plyr播放器提供以下API:

```typescript
// 基础播放控制
player.play();            // 播放
player.pause();           // 暂停
player.stop();            // 停止
player.restart();         // 重新播放
player.rewind(10);        // 后退10秒
player.forward(10);       // 前进10秒
player.increaseVolume(0.1); // 增加10%音量
player.decreaseVolume(0.1); // 减少10%音量
player.togglePlay();      // 切换播放/暂停
player.toggleMute();      // 切换静音/非静音

// 状态获取
player.isPlaying();       // 是否正在播放
player.isPaused();        // 是否已暂停
player.playing;           // 播放状态
player.paused;            // 暂停状态
player.stopped;           // 停止状态

// 媒体属性
player.volume = 0.8;      // 设置音量(0-1)
player.muted = true;      // 设置静音
player.currentTime = 30;  // 设置当前播放位置(秒)
player.speed = 1.5;       // 设置播放速度

// 增强功能
player.getContainer();    // 获取容器元素
player.getDefaultOptions(); // 获取默认选项
player.setSource(newSource); // 设置新媒体源
player.changeAspectRatio('4:3'); // 修改视频比例
player.addShortcut('m', () => player.toggleMute()); // 添加快捷键
player.getCaptureImage(); // 截取当前画面
player.downloadMedia('video.mp4'); // 下载媒体
player.setPoster('https://example.com/poster.jpg'); // 设置视频封面
player.isFullscreen();    // 是否全屏
player.enterPictureInPicture(); // 进入画中画模式
player.exitPictureInPicture();  // 退出画中画模式
player.togglePictureInPicture(); // 切换画中画模式
player.reload();          // 重新加载媒体
player.getQualityOptions(); // 获取可用质量选项
player.setQuality('720'); // 设置视频质量
player.getSpeedOptions(); // 获取可用速度选项
player.setCustomControls(['play', 'volume']); // 设置自定义控制栏
player.addMarker(45, '精彩片段'); // 添加时间轴标记
player.removeMarker(45);  // 移除标记
player.clearMarkers();    // 清除所有标记

// 事件监听
player.on('play', () => console.log('开始播放'));
player.once('ended', () => console.log('播放结束'));
player.off('play', callback); // 移除事件监听
```

#### 播放列表API

```typescript
// 播放列表控制器
const { 
  player,                   // 播放器实例
  next,                     // 播放下一个函数
  previous,                 // 播放上一个函数
  playIndex,                // 播放指定索引函数
  currentIndex,             // 当前播放索引
  sources                   // 媒体源列表
} = await createPlaylist(sources, container, options);

// 使用举例
next();                     // 播放下一个
previous();                 // 播放上一个
playIndex(2);               // 播放索引为2的媒体
const currentPlaying = sources[currentIndex]; // 获取当前播放的媒体信息
```

#### 适用场景

- **视频教学平台**: 创建支持视频标记、截图和高级控制的视频播放器
- **在线视频点播**: 构建支持多清晰度、字幕和自定义UI的专业播放器
- **音频播放应用**: 结合播放列表功能创建音频播放器
- **混合媒体展示**: 支持在同一播放器中无缝切换视频和音频
- **Vue应用集成**: 在Vue应用中轻松集成高级媒体播放功能

### 🔌 WebSocket 工具 (WebSocket Utils)

提供高效可靠的 WebSocket 连接管理和通信工具。

- `createWebSocketClient(options: WebSocketOptions): WebSocketClient` - 创建一个 WebSocket 客户端
- `isWebSocketSupported(): boolean` - 检查当前环境是否支持 WebSocket

#### WebSocket 客户端 API

WebSocket 客户端 (`WebSocketClient`) 提供以下核心功能：

- **自动重连** - 网络中断时自动尝试重新连接
- **心跳检测** - 保持连接活跃并检测断线
- **消息队列** - 离线时自动缓存消息，连接恢复后发送
- **消息优先级** - 支持高、中、低三种优先级消息处理
- **事件系统** - 提供丰富的事件监听接口
- **批量发送** - 支持消息批处理以优化网络传输
- **超时处理** - 自动处理消息超时和重试
- **完整指标** - 提供详细的连接和性能统计数据

#### 基本使用示例

```typescript
import { WebSocketClient, WebSocketState, MessagePriority } from 'mstf-kit';

// 创建 WebSocket 客户端
const ws = new WebSocketClient({
  url: 'wss://example.com/socket',
  protocols: ['v1'],
  debug: true,               // 启用调试日志
  connectionTimeout: 8000,   // 连接超时 (ms)
  
  // 心跳配置
  heartbeat: {
    enabled: true,
    interval: 30000,         // 每30秒发送一次心跳
    message: { type: 'ping' },
    timeout: 5000            // 心跳5秒无响应判定为超时
  },
  
  // 自动重连配置
  reconnect: {
    enabled: true,
    maxRetries: 10,          // 最多重试10次
    initialDelay: 1000,      // 初始重试延迟1秒
    maxDelay: 30000,         // 最大重试延迟30秒
    factor: 1.5,             // 指数退避系数
    jitter: 0.5              // 随机抖动系数
  }
});

// 连接到服务器
ws.connect()
  .then(() => {
    console.log('连接成功');
    
    // 发送消息
    return ws.send({ type: 'hello', data: 'world' });
  })
  .catch(error => {
    console.error('连接错误:', error);
  });

// 监听消息
ws.on('message', data => {
  console.log('收到消息:', data);
});

// 监听连接状态变化
ws.on('close', event => {
  console.log('连接关闭:', event.code);
});

ws.on('reconnect', attempt => {
  console.log(`重连成功 (第${attempt}次尝试)`);
});

// 发送不同优先级的消息
ws.send(criticalData, { priority: MessagePriority.HIGH });
ws.send(normalData, { priority: MessagePriority.NORMAL });
ws.send(statsData, { priority: MessagePriority.LOW });

// 期望服务器响应的消息
ws.send({ type: 'query', id: 'user-123' }, {
  expectResponse: true,      // 等待响应
  timeout: 5000,             // 响应超时时间
  retries: 2,                // 超时后重试次数
  retryDelay: 1000           // 重试间隔
}).then(response => {
  console.log('收到响应:', response);
}).catch(error => {
  console.error('请求失败:', error);
});

// 获取连接状态和统计信息
console.log('当前状态:', ws.getState());
console.log('连接延迟:', ws.getLatency());
console.log('统计信息:', ws.getConnectionStats());

// 不再使用时销毁资源
ws.destroy();
```

#### 高级特性

- **批量消息**: 适用于需要发送大量小消息的场景，自动合并为批量消息减少网络开销
- **动态配置**: 可在运行时调整心跳、重连、消息处理等配置
- **完整生命周期管理**: 自动处理资源释放，防止内存泄漏
- **兼容性**: 支持各种浏览器环境和 Node.js

更多高级用法详见 API 文档。

## 📄 许可证

[MIT](./LICENSE) © [mustafa]