Files
OrionTV/Plan.md
Neil.X.Zhang 3b79d06b7d Update
2025-06-27 16:16:14 +08:00

12 KiB
Raw Blame History

MoonTV 到 MyTv 迁移可行性分析与方案

项目概述

MoonTV 项目分析

项目定位: 基于 Next.js 的 Web 端影视聚合播放器

核心技术栈:

  • 前端框架: Next.js 14 (App Router)
  • UI 库: Tailwind CSS + React
  • 语言: TypeScript
  • 视频播放器: ArtPlayer + HLS.js
  • 状态管理: React Hooks + LocalStorage
  • 部署: Docker + Vercel

核心功能:

  1. 多源影视资源聚合搜索
  2. 在线视频播放 (支持 HLS 流)
  3. 影片详情展示 (演员、年份、简介等)
  4. 收藏功能 (LocalStorage)
  5. 播放记录 (继续观看)
  6. 响应式布局 (桌面 + 移动端)
  7. PWA 支持

项目结构:

MoonTV/
├── src/
│   ├── app/                 # Next.js 14 App Router 页面
│   │   ├── (pages)/        # 主要页面路由
│   │   ├── api/            # 后端 API 路由
│   │   │   ├── douban/     # 豆瓣 API 集成
│   │   │   ├── search/     # 多源搜索 API
│   │   │   ├── detail/     # 影片详情 API
│   │   │   └── login/      # 认证 API
│   │   └── globals.css     # 全局样式
│   ├── components/         # React 组件
│   │   ├── VideoCard.tsx   # 视频卡片组件
│   │   ├── AggregateCard.tsx # 聚合卡片组件
│   │   ├── ScrollableRow.tsx # 横向滚动容器
│   │   └── ...
│   └── lib/               # 工具库
│       ├── types.ts       # TypeScript 类型定义
│       ├── db.client.ts   # 本地存储操作
│       └── config.ts      # 配置管理
├── config.json           # 影视资源站点配置
└── package.json          # 项目依赖

MyTv 项目分析

项目定位: 基于 React Native TV 的电视端应用

核心技术栈:

  • 框架: React Native TV (支持 Apple TV + Android TV)
  • 导航: Expo Router (文件系统路由)
  • 视频播放: react-native-media-console
  • 配置: @react-native-tvos/config-tv
  • 语言: TypeScript

核心功能:

  1. TV 遥控器导航支持
  2. 焦点管理和高亮显示
  3. 视频播放 (react-native-video)
  4. TV 专用 UI 组件
  5. 跨平台支持 (Apple TV + Android TV)

迁移可行性分析

高度可行的方面

1. 核心业务逻辑

  • 数据结构兼容: MoonTV 的 VideoDetail 类型定义可直接复用
  • API 接口复用: MoonTV 的搜索、详情 API 可通过网络请求在 TV 端调用
  • 业务流程一致: 搜索 → 详情 → 播放的核心流程完全匹配

2. 功能特性映射

MoonTV 功能 MyTv 对应功能 迁移难度
多源搜索 网络 API 调用 容易
影片详情 详情页面适配 中等
视频播放 react-native-video 中等
收藏功能 AsyncStorage 容易
播放记录 AsyncStorage 容易

3. 技术栈兼容性

  • TypeScript: 两个项目都使用 TypeScript类型定义可复用
  • React 生态: 核心 React 概念一致,组件逻辑可借鉴
  • 状态管理: 都使用 Hooks状态逻辑可迁移

⚠️ 需要重点关注的挑战

1. UI/UX 差异

  • 交互模式: Web 鼠标/触摸 → TV 遥控器 D-Pad 导航
  • 布局设计: 响应式网页布局 → TV 固定尺寸界面
  • 焦点管理: Web 无需焦点 → TV 必须精确控制焦点流转

2. 视频播放器差异

  • MoonTV: ArtPlayer (Web) + HLS.js
  • MyTv: react-native-media-console + react-native-video
  • 挑战: 播放控制、进度管理、字幕等功能需要重新实现

3. 存储机制差异

  • MoonTV: LocalStorage (同步)
  • MyTv: AsyncStorage (异步)
  • 影响: 所有本地存储操作需要异步化改造

不可直接迁移的方面

1. Web 特定功能

  • PWA 功能 (离线缓存、安装到桌面)
  • 豆瓣 API 的 CORS 处理
  • 浏览器特定的媒体 API

2. 部署和分发

  • Docker/Vercel 部署 → App Store/Google Play 发布
  • Web 更新 → 应用商店审核流程

迁移方案设计

方案 A: 渐进式迁移 (推荐)

阶段 1: 基础架构搭建 (1-2 周)

  1. 创建 TV 端项目结构

    MyTv/
    ├── app/
       ├── (tabs)/
          ├── home.tsx      # 首页 - 影片推荐
          ├── search.tsx    # 搜索页
          ├── library.tsx   # 我的收藏/播放记录
          └── settings.tsx  # 设置页
       ├── detail/
          └── [id].tsx      # 影片详情页
       └── play/
           └── [id].tsx      # 播放页面
    ├── components/
       ├── TVVideoCard.tsx   # TV 适配的视频卡片
       ├── TVSearchInput.tsx # TV 搜索输入
       ├── TVMediaPlayer.tsx # TV 媒体播放器
       └── FocusableView.tsx # 可获取焦点的容器
    ├── services/
       ├── api.ts           # MoonTV API 调用封装
       ├── storage.ts       # AsyncStorage 封装
       └── player.ts        # 播放器控制逻辑
    └── types/
        └── index.ts         #  MoonTV 迁移的类型定义
    
  2. 核心服务层迁移

    // services/api.ts - 调用 MoonTV 后端
    class MoonTVAPI {
      private baseURL = "https://your-moontv-instance.com/api";
    
      async search(query: string): Promise<SearchResult[]> {
        const response = await fetch(`${this.baseURL}/search?q=${query}`);
        return response.json();
      }
    
      async getDetail(source: string, id: string): Promise<VideoDetail> {
        const response = await fetch(
          `${this.baseURL}/detail?source=${source}&id=${id}`
        );
        return response.json();
      }
    }
    
  3. 存储层适配

    // services/storage.ts
    import AsyncStorage from "@react-native-async-storage/async-storage";
    
    export class TVStorage {
      static async getFavorites(): Promise<string[]> {
        const data = await AsyncStorage.getItem("favorites");
        return data ? JSON.parse(data) : [];
      }
    
      static async addFavorite(videoId: string): Promise<void> {
        const favorites = await this.getFavorites();
        if (!favorites.includes(videoId)) {
          favorites.push(videoId);
          await AsyncStorage.setItem("favorites", JSON.stringify(favorites));
        }
      }
    }
    

阶段 2: 核心页面开发 (2-3 周)

  1. 搜索功能实现

    // app/(tabs)/search.tsx
    export default function SearchScreen() {
      const [query, setQuery] = useState("");
      const [results, setResults] = useState<SearchResult[]>([]);
      const [focusedIndex, setFocusedIndex] = useState(0);
    
      const handleSearch = async (text: string) => {
        const searchResults = await MoonTVAPI.search(text);
        setResults(searchResults);
      };
    
      return (
        <TVFocusableView>
          <TVSearchInput
            value={query}
            onChangeText={setQuery}
            onSubmit={handleSearch}
          />
          <FlatList
            data={results}
            renderItem={({ item, index }) => (
              <TVVideoCard
                video={item}
                focused={index === focusedIndex}
                onFocus={() => setFocusedIndex(index)}
              />
            )}
            keyExtractor={(item) => item.id}
          />
        </TVFocusableView>
      );
    }
    
  2. 详情页面开发

    // app/detail/[id].tsx
    export default function DetailScreen() {
      const { id, source } = useLocalSearchParams();
      const [detail, setDetail] = useState<VideoDetail | null>(null);
    
      useEffect(() => {
        MoonTVAPI.getDetail(source as string, id as string).then(setDetail);
      }, [source, id]);
    
      return (
        <ScrollView>
          <TVDetailHeader video={detail} />
          <TVEpisodeList episodes={detail?.episodes} />
          <TVActionButtons onPlay={handlePlay} onFavorite={handleFavorite} />
        </ScrollView>
      );
    }
    

阶段 3: 播放功能集成 (1-2 周)

  1. 播放器组件开发

    // components/TVMediaPlayer.tsx
    import VideoPlayer from "react-native-media-console";
    
    export function TVMediaPlayer({ source, title }: TVMediaPlayerProps) {
      return (
        <VideoPlayer
          source={{ uri: source }}
          title={title}
          disableControls={false}
          resizeMode="contain"
          onEnd={handlePlaybackEnd}
          tapAnywhereToPause={true}
        />
      );
    }
    
  2. 播放页面开发

    // app/play/[id].tsx
    export default function PlayScreen() {
      const { videoUrl, title } = useLocalSearchParams();
    
      return (
        <View style={{ flex: 1, backgroundColor: "black" }}>
          <TVMediaPlayer source={videoUrl as string} title={title as string} />
        </View>
      );
    }
    

阶段 4: TV 专用优化 (1-2 周)

  1. 焦点导航优化

    // components/FocusableView.tsx
    export function FocusableView({ children, onFocus, onBlur }: Props) {
      return (
        <Pressable
          onFocus={onFocus}
          onBlur={onBlur}
          style={({ focused }) => [styles.container, focused && styles.focused]}
        >
          {children}
        </Pressable>
      );
    }
    
  2. 遥控器快捷键支持

    // hooks/useRemoteControl.ts
    export function useRemoteControl() {
      useEffect(() => {
        const handleKeyPress = (event: any) => {
          switch (event.key) {
            case "ArrowUp": // 遥控器上键
              // 处理向上导航
              break;
            case "ArrowDown": // 遥控器下键
              // 处理向下导航
              break;
            case "Select": // 遥控器确定键
              // 处理选择
              break;
          }
        };
    
        // 注册事件监听器
      }, []);
    }
    

方案 B: API 服务复用 (备选)

如果不想完全迁移前端,可以保持 MoonTV 作为 API 服务器MyTv 作为纯客户端:

// MyTv 通过网络调用 MoonTV 的 API
const MOONTV_API_BASE = "https://your-moontv-instance.com/api";

class MoonTVClient {
  async search(query: string) {
    return fetch(`${MOONTV_API_BASE}/search?q=${query}`);
  }

  async getVideoDetail(source: string, id: string) {
    return fetch(`${MOONTV_API_BASE}/detail?source=${source}&id=${id}`);
  }
}

实施建议

开发优先级

  1. 高优先级 (核心功能)

    • 基础 TV 导航框架
    • 视频搜索和播放
    • 遥控器支持
  2. 中优先级 (用户体验)

    • 收藏和播放记录
    • 详情页面丰富化
    • 性能优化
  3. 低优先级 (增值功能)

    • 个性化推荐
    • 多用户支持
    • 云同步

技术风险与缓解

风险 影响 缓解措施
TV 焦点管理复杂 开发周期延长 早期原型验证,分步实现
视频播放兼容性 功能不稳定 多设备测试,备用播放器方案
API 调用延迟 用户体验差 本地缓存,异步加载
应用商店审核 发布延期 提前了解审核规则,合规设计

开发资源估算

  • 开发时间: 6-8 周 (1-2 人团队)
  • 技术栈学习: React Native TV (1-2 周)
  • UI/UX 设计: TV 界面设计 (1 周)
  • 测试验证: 多设备兼容性 (1 周)

结论

迁移可行性: ☆ (高度可行)

推荐方案: 渐进式迁移,保持 MoonTV 作为后端 API 服务,开发独立的 MyTv 客户端

关键成功因素:

  1. 合理的架构设计 (分离 API 和 UI)
  2. TV 交互模式的深度理解
  3. 充分的设备兼容性测试
  4. 渐进式开发和验证

通过这个方案,可以充分利用 MoonTV 的成熟后端能力,同时为 TV 平台提供原生的使用体验。