File size: 3,268 Bytes
d47b053
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
 * 文件工具函数
 * 文件查找、路径处理
 */

import * as fs from 'fs'
import * as path from 'path'

/**
 * 获取质量对应的分辨率字符串
 */
export function getResolutionForQuality(quality: string): string {
  const resolutions: Record<string, string> = {
    low: '480p',
    medium: '720p',
    high: '1080p'
  }
  return resolutions[quality] || '480p'
}

/**
 * 查找视频文件
 * 支持动态帧率(如 480p15, 480p30, 1080p60 等)
 */
export function findVideoFile(mediaDir: string, quality: string, frameRate?: number): string | null {
  const resolution = getResolutionForQuality(quality)
  const expectedFrameRate = frameRate || 30

  // 首先尝试兼容旧逻辑的固定命名。
  const folderWithFrameRate = `${resolution}${expectedFrameRate}`
  const expectedPath = path.join(mediaDir, 'videos', 'scene', folderWithFrameRate, 'MainScene.mp4')
  if (fs.existsSync(expectedPath)) {
    return expectedPath
  }

  return findLatestFileByExtension(mediaDir, '.mp4')
}

/**
 * 查找图片文件
 */
export function findImageFile(mediaDir: string, sceneName?: string): string | null {
  if (sceneName) {
    const sceneImage = findFileRecursive(mediaDir, `${sceneName}.png`)
    if (sceneImage) {
      return sceneImage
    }
  }

  return findFirstFileByExtension(mediaDir, '.png')
}

/**
 * 递归查找文件
 */
export function findFileRecursive(dir: string, filename: string): string | null {
  try {
    const entries = fs.readdirSync(dir, { withFileTypes: true })

    for (const entry of entries) {
      const fullPath = path.join(dir, entry.name)

      if (entry.isDirectory()) {
        const found = findFileRecursive(fullPath, filename)
        if (found) return found
      } else if (entry.name === filename) {
        return fullPath
      }
    }
  } catch {
    // 忽略错误
  }

  return null
}

function findLatestFileByExtension(dir: string, ext: string): string | null {
  const matches: Array<{ path: string; mtimeMs: number }> = []

  try {
    collectFilesByExtension(dir, ext, matches)
  } catch {
    return null
  }

  matches.sort((left, right) => right.mtimeMs - left.mtimeMs)
  return matches[0]?.path ?? null
}

function collectFilesByExtension(dir: string, ext: string, matches: Array<{ path: string; mtimeMs: number }>): void {
  const entries = fs.readdirSync(dir, { withFileTypes: true })
  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name)
    if (entry.isDirectory()) {
      collectFilesByExtension(fullPath, ext, matches)
      continue
    }

    if (entry.name.toLowerCase().endsWith(ext.toLowerCase())) {
      const stat = fs.statSync(fullPath)
      matches.push({ path: fullPath, mtimeMs: stat.mtimeMs })
    }
  }
}

function findFirstFileByExtension(dir: string, ext: string): string | null {
  try {
    const entries = fs.readdirSync(dir, { withFileTypes: true })
    for (const entry of entries) {
      const fullPath = path.join(dir, entry.name)
      if (entry.isDirectory()) {
        const found = findFirstFileByExtension(fullPath, ext)
        if (found) return found
      } else if (entry.name.toLowerCase().endsWith(ext.toLowerCase())) {
        return fullPath
      }
    }
  } catch {
    // 忽略错误
  }

  return null
}