File size: 2,312 Bytes
94e1b2f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import fs from 'fs'
import path from 'path'
import { createHash } from 'crypto'

const RENDER_CACHE_ROOT = path.join(process.cwd(), '.studio-workspace', 'render-cache')

export interface RenderCacheWorkspace {
  key: string
  rootDir: string
  tempDir: string
  mediaDir: string
  codeFile: string
}

function normalizeRenderCacheKey(renderCacheKey: string): string {
  const trimmed = renderCacheKey.trim()
  if (!trimmed) {
    throw new Error('renderCacheKey must not be empty')
  }
  return trimmed
}

function toDirectoryName(renderCacheKey: string): string {
  const normalized = normalizeRenderCacheKey(renderCacheKey)
  const readable = normalized
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
    .slice(0, 48) || 'render-cache'
  const digest = createHash('sha1').update(normalized).digest('hex').slice(0, 12)
  return `${readable}-${digest}`
}

function ensureWorkspace(rootDir: string): void {
  fs.mkdirSync(rootDir, { recursive: true })
}

export function resolveRenderCacheWorkspace(
  renderCacheKey: string,
  scope: 'video' | 'image',
  blockIndex?: number
): RenderCacheWorkspace {
  const directoryName = toDirectoryName(renderCacheKey)
  const scopeSuffix =
    scope === 'video'
      ? 'video'
      : `image-${String(blockIndex ?? 0).padStart(3, '0')}`
  const rootDir = path.join(RENDER_CACHE_ROOT, directoryName, scopeSuffix)
  const mediaDir = path.join(rootDir, 'media')
  const codeFile = path.join(rootDir, 'scene.py')

  ensureWorkspace(mediaDir)

  return {
    key: renderCacheKey,
    rootDir,
    tempDir: rootDir,
    mediaDir,
    codeFile
  }
}

export function buildClassicRenderCacheKey(
  clientId: string | undefined,
  outputMode: 'video' | 'image',
  requestedKey?: string
): string {
  const normalizedRequested = requestedKey?.trim()
  if (normalizedRequested) {
    return normalizedRequested
  }

  const normalizedClientId = clientId?.trim() || 'anonymous'
  return `classic-${normalizedClientId}-${outputMode}`
}

export function buildStudioRenderCacheKey(
  sessionId: string,
  outputMode: 'video' | 'image',
  workId?: string
): string {
  const normalizedWorkId = workId?.trim()
  if (normalizedWorkId) {
    return `studio-${sessionId}-${outputMode}-${normalizedWorkId}`
  }
  return `studio-${sessionId}-${outputMode}`
}