@su-record/vibe 2.7.3 → 2.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/cli/commands/init.d.ts +2 -2
  2. package/dist/cli/commands/init.d.ts.map +1 -1
  3. package/dist/cli/commands/init.js +34 -6
  4. package/dist/cli/commands/init.js.map +1 -1
  5. package/dist/cli/commands/update.d.ts.map +1 -1
  6. package/dist/cli/commands/update.js +18 -2
  7. package/dist/cli/commands/update.js.map +1 -1
  8. package/dist/cli/detect.d.ts.map +1 -1
  9. package/dist/cli/detect.js +28 -1
  10. package/dist/cli/detect.js.map +1 -1
  11. package/dist/cli/llm/gpt-commands.d.ts +1 -0
  12. package/dist/cli/llm/gpt-commands.d.ts.map +1 -1
  13. package/dist/cli/llm/gpt-commands.js +14 -0
  14. package/dist/cli/llm/gpt-commands.js.map +1 -1
  15. package/dist/cli/postinstall/constants.d.ts +10 -4
  16. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  17. package/dist/cli/postinstall/constants.js +19 -6
  18. package/dist/cli/postinstall/constants.js.map +1 -1
  19. package/dist/cli/postinstall/index.d.ts +1 -1
  20. package/dist/cli/postinstall/index.d.ts.map +1 -1
  21. package/dist/cli/postinstall/index.js +1 -1
  22. package/dist/cli/postinstall/index.js.map +1 -1
  23. package/dist/cli/postinstall.d.ts +1 -1
  24. package/dist/cli/postinstall.d.ts.map +1 -1
  25. package/dist/cli/postinstall.js +1 -1
  26. package/dist/cli/postinstall.js.map +1 -1
  27. package/dist/cli/setup/Provisioner.d.ts +28 -0
  28. package/dist/cli/setup/Provisioner.d.ts.map +1 -0
  29. package/dist/cli/setup/Provisioner.js +201 -0
  30. package/dist/cli/setup/Provisioner.js.map +1 -0
  31. package/dist/cli/types.d.ts +1 -0
  32. package/dist/cli/types.d.ts.map +1 -1
  33. package/dist/infra/lib/TaskContext.d.ts +43 -0
  34. package/dist/infra/lib/TaskContext.d.ts.map +1 -0
  35. package/dist/infra/lib/TaskContext.js +84 -0
  36. package/dist/infra/lib/TaskContext.js.map +1 -0
  37. package/dist/infra/lib/TokenBudgetTracker.d.ts +55 -0
  38. package/dist/infra/lib/TokenBudgetTracker.d.ts.map +1 -0
  39. package/dist/infra/lib/TokenBudgetTracker.js +150 -0
  40. package/dist/infra/lib/TokenBudgetTracker.js.map +1 -0
  41. package/dist/infra/lib/constants.d.ts +5 -0
  42. package/dist/infra/lib/constants.d.ts.map +1 -1
  43. package/dist/infra/lib/constants.js +6 -0
  44. package/dist/infra/lib/constants.js.map +1 -1
  45. package/dist/infra/lib/gpt/auth.d.ts +18 -2
  46. package/dist/infra/lib/gpt/auth.d.ts.map +1 -1
  47. package/dist/infra/lib/gpt/auth.js +91 -7
  48. package/dist/infra/lib/gpt/auth.js.map +1 -1
  49. package/dist/infra/lib/gpt/chat.d.ts.map +1 -1
  50. package/dist/infra/lib/gpt/chat.js +1 -0
  51. package/dist/infra/lib/gpt/chat.js.map +1 -1
  52. package/dist/infra/lib/gpt/types.d.ts +1 -1
  53. package/dist/infra/lib/gpt/types.d.ts.map +1 -1
  54. package/dist/infra/lib/memory/SessionRAGRetriever.d.ts +1 -0
  55. package/dist/infra/lib/memory/SessionRAGRetriever.d.ts.map +1 -1
  56. package/dist/infra/lib/memory/SessionRAGRetriever.js +46 -21
  57. package/dist/infra/lib/memory/SessionRAGRetriever.js.map +1 -1
  58. package/dist/infra/lib/memory/SessionRAGStore.d.ts +5 -0
  59. package/dist/infra/lib/memory/SessionRAGStore.d.ts.map +1 -1
  60. package/dist/infra/lib/memory/SessionRAGStore.js +46 -12
  61. package/dist/infra/lib/memory/SessionRAGStore.js.map +1 -1
  62. package/dist/infra/lib/memory/index.d.ts +4 -0
  63. package/dist/infra/lib/memory/index.d.ts.map +1 -1
  64. package/dist/infra/lib/memory/index.js +4 -0
  65. package/dist/infra/lib/memory/index.js.map +1 -1
  66. package/dist/infra/orchestrator/AgentManifestCache.d.ts +54 -0
  67. package/dist/infra/orchestrator/AgentManifestCache.d.ts.map +1 -0
  68. package/dist/infra/orchestrator/AgentManifestCache.js +191 -0
  69. package/dist/infra/orchestrator/AgentManifestCache.js.map +1 -0
  70. package/dist/infra/orchestrator/agentDiscovery.d.ts +8 -0
  71. package/dist/infra/orchestrator/agentDiscovery.d.ts.map +1 -1
  72. package/dist/infra/orchestrator/agentDiscovery.js +2 -2
  73. package/dist/infra/orchestrator/agentDiscovery.js.map +1 -1
  74. package/dist/infra/orchestrator/index.d.ts +3 -1
  75. package/dist/infra/orchestrator/index.d.ts.map +1 -1
  76. package/dist/infra/orchestrator/index.js +3 -1
  77. package/dist/infra/orchestrator/index.js.map +1 -1
  78. package/dist/tools/semantic/astGrep.d.ts +2 -0
  79. package/dist/tools/semantic/astGrep.d.ts.map +1 -1
  80. package/dist/tools/semantic/astGrep.js +61 -35
  81. package/dist/tools/semantic/astGrep.js.map +1 -1
  82. package/dist/tools/semantic/astGrep.test.js +9 -1
  83. package/dist/tools/semantic/astGrep.test.js.map +1 -1
  84. package/hooks/scripts/context-save.js +12 -0
  85. package/package.json +4 -2
  86. package/skills/characterization-test/SKILL.md +202 -0
  87. package/skills/video-production/SKILL.md +222 -0
@@ -0,0 +1,222 @@
1
+ ---
2
+ name: video-production
3
+ description: "Video processing and production patterns — FFmpeg, transcoding, streaming, subtitles."
4
+ triggers: [video, ffmpeg, transcode, encode, stream, media, subtitle, thumbnail, hls, dash]
5
+ priority: 60
6
+ ---
7
+
8
+ # Video Production Skill
9
+
10
+ FFmpeg 기반 비디오 처리, 트랜스코딩, 스트리밍 구성, 자막 처리 패턴 가이드.
11
+
12
+ ## Core Concepts
13
+
14
+ ### FFmpeg CLI Wrapper Pattern
15
+
16
+ FFmpeg 호출은 반드시 래퍼를 통해 수행한다. 직접 CLI 문자열을 조합하지 않는다.
17
+
18
+ **TypeScript (fluent-ffmpeg):**
19
+ ```typescript
20
+ import ffmpeg from 'fluent-ffmpeg';
21
+
22
+ function transcodeVideo(
23
+ input: string,
24
+ output: string,
25
+ options: TranscodeOptions,
26
+ ): Promise<void> {
27
+ return new Promise((resolve, reject) => {
28
+ ffmpeg(input)
29
+ .outputOptions(buildOutputOptions(options))
30
+ .output(output)
31
+ .on('end', resolve)
32
+ .on('error', reject)
33
+ .run();
34
+ });
35
+ }
36
+ ```
37
+
38
+ **Python (ffmpeg-python):**
39
+ ```python
40
+ import ffmpeg
41
+
42
+ def transcode_video(
43
+ input_path: str,
44
+ output_path: str,
45
+ codec: str = "libx264",
46
+ crf: int = 23,
47
+ ) -> None:
48
+ (
49
+ ffmpeg
50
+ .input(input_path)
51
+ .output(output_path, vcodec=codec, crf=crf)
52
+ .overwrite_output()
53
+ .run(capture_stdout=True, capture_stderr=True)
54
+ )
55
+ ```
56
+
57
+ ### Error Handling
58
+
59
+ 비디오 처리는 실패할 수 있다. 반드시 에러를 처리한다.
60
+
61
+ | 에러 유형 | 원인 | 대응 |
62
+ |-----------|------|------|
63
+ | Codec not found | FFmpeg 빌드에 코덱 미포함 | 런타임 시 코덱 가용성 확인 |
64
+ | Out of memory | 큰 파일 + 고해상도 | 스트리밍 처리, chunk 분할 |
65
+ | Corrupted input | 깨진 소스 파일 | `ffprobe`로 사전 검증 |
66
+ | Permission denied | 파일 잠금 | 임시 디렉토리 사용, 정리 보장 |
67
+ | Timeout | 장시간 인코딩 | progress 콜백 + 타임아웃 설정 |
68
+
69
+ ```typescript
70
+ // 입력 파일 사전 검증
71
+ async function probeVideo(filePath: string): Promise<VideoMetadata> {
72
+ return new Promise((resolve, reject) => {
73
+ ffmpeg.ffprobe(filePath, (err, data) => {
74
+ if (err) return reject(new Error(`Invalid video: ${err.message}`));
75
+ const video = data.streams.find(s => s.codec_type === 'video');
76
+ if (!video) return reject(new Error('No video stream found'));
77
+ resolve({
78
+ width: video.width ?? 0,
79
+ height: video.height ?? 0,
80
+ duration: Number(data.format.duration ?? 0),
81
+ codec: video.codec_name ?? 'unknown',
82
+ bitrate: Number(data.format.bit_rate ?? 0),
83
+ });
84
+ });
85
+ });
86
+ }
87
+ ```
88
+
89
+ ## Common Operations
90
+
91
+ ### Thumbnail Generation
92
+
93
+ ```typescript
94
+ function extractThumbnail(
95
+ input: string,
96
+ output: string,
97
+ timeSeconds: number = 1,
98
+ ): Promise<void> {
99
+ return new Promise((resolve, reject) => {
100
+ ffmpeg(input)
101
+ .screenshots({
102
+ timestamps: [timeSeconds],
103
+ filename: path.basename(output),
104
+ folder: path.dirname(output),
105
+ size: '320x240',
106
+ })
107
+ .on('end', resolve)
108
+ .on('error', reject);
109
+ });
110
+ }
111
+ ```
112
+
113
+ ### Resolution Presets
114
+
115
+ | Preset | Resolution | Bitrate (H.264) | Use Case |
116
+ |--------|-----------|-----------------|----------|
117
+ | 360p | 640x360 | 800 kbps | Mobile preview |
118
+ | 480p | 854x480 | 1.5 Mbps | Standard mobile |
119
+ | 720p | 1280x720 | 3 Mbps | HD streaming |
120
+ | 1080p | 1920x1080 | 6 Mbps | Full HD |
121
+ | 4K | 3840x2160 | 15 Mbps | Ultra HD |
122
+
123
+ ### Codec Selection
124
+
125
+ | Codec | Format | Pros | Cons |
126
+ |-------|--------|------|------|
127
+ | H.264 (libx264) | MP4 | Universal compatibility | Larger file size |
128
+ | H.265 (libx265) | MP4 | 50% smaller than H.264 | Slower encoding, licensing |
129
+ | VP9 (libvpx-vp9) | WebM | Open source, good quality | Slow encoding |
130
+ | AV1 (libaom-av1) | MP4/WebM | Best compression | Very slow encoding |
131
+
132
+ ### HLS Streaming
133
+
134
+ ```typescript
135
+ function generateHLS(
136
+ input: string,
137
+ outputDir: string,
138
+ variants: HLSVariant[] = DEFAULT_VARIANTS,
139
+ ): Promise<void> {
140
+ return new Promise((resolve, reject) => {
141
+ const cmd = ffmpeg(input);
142
+ for (const v of variants) {
143
+ cmd
144
+ .output(path.join(outputDir, `${v.name}.m3u8`))
145
+ .outputOptions([
146
+ `-vf scale=${v.width}:${v.height}`,
147
+ `-b:v ${v.bitrate}`,
148
+ '-hls_time 6',
149
+ '-hls_list_size 0',
150
+ '-hls_segment_filename',
151
+ path.join(outputDir, `${v.name}_%03d.ts`),
152
+ ]);
153
+ }
154
+ cmd.on('end', resolve).on('error', reject).run();
155
+ });
156
+ }
157
+ ```
158
+
159
+ ### Subtitle Processing
160
+
161
+ ```typescript
162
+ // SRT → VTT 변환
163
+ function srtToVtt(srtContent: string): string {
164
+ const vtt = srtContent
165
+ .replace(/\r\n/g, '\n')
166
+ .replace(/(\d{2}):(\d{2}):(\d{2}),(\d{3})/g, '$1:$2:$3.$4');
167
+ return `WEBVTT\n\n${vtt}`;
168
+ }
169
+
170
+ // 자막 burn-in (하드코딩)
171
+ function burnSubtitles(
172
+ input: string,
173
+ subtitleFile: string,
174
+ output: string,
175
+ ): Promise<void> {
176
+ return new Promise((resolve, reject) => {
177
+ ffmpeg(input)
178
+ .outputOptions([`-vf subtitles=${subtitleFile}`])
179
+ .output(output)
180
+ .on('end', resolve)
181
+ .on('error', reject)
182
+ .run();
183
+ });
184
+ }
185
+ ```
186
+
187
+ ### Watermark
188
+
189
+ ```typescript
190
+ function addWatermark(
191
+ input: string,
192
+ watermark: string,
193
+ output: string,
194
+ position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' = 'bottom-right',
195
+ ): Promise<void> {
196
+ const overlayMap: Record<string, string> = {
197
+ 'top-left': '10:10',
198
+ 'top-right': 'W-w-10:10',
199
+ 'bottom-left': '10:H-h-10',
200
+ 'bottom-right': 'W-w-10:H-h-10',
201
+ };
202
+ return new Promise((resolve, reject) => {
203
+ ffmpeg(input)
204
+ .input(watermark)
205
+ .complexFilter([`overlay=${overlayMap[position]}`])
206
+ .output(output)
207
+ .on('end', resolve)
208
+ .on('error', reject)
209
+ .run();
210
+ });
211
+ }
212
+ ```
213
+
214
+ ## Best Practices
215
+
216
+ 1. **항상 ffprobe로 입력 검증** — 처리 전에 코덱, 해상도, 무결성 확인
217
+ 2. **임시 파일 정리 보장** — try/finally 또는 cleanup handler 사용
218
+ 3. **Progress 콜백 구현** — 장시간 작업에 진행률 피드백
219
+ 4. **스트리밍 처리 선호** — 대용량 파일은 메모리에 올리지 않음
220
+ 5. **코덱 가용성 런타임 확인** — `ffmpeg -codecs`로 빌드 지원 확인
221
+ 6. **CRF 기반 품질 제어** — 비트레이트 고정보다 CRF (18-28) 사용
222
+ 7. **하드웨어 가속 활용** — NVIDIA NVENC, Intel QSV, Apple VideoToolbox 가용 시 사용