kasaframe 0.1.4 โ 0.1.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.
- package/NOTICE +311 -0
- package/README.md +18 -5
- package/docs/AGENTS.md +2 -1
- package/package.json +1 -1
- package/packages/adapters/src/project.ts +2 -0
- package/packages/check/package.json +1 -0
- package/packages/check/src/check.ts +8 -2
- package/packages/check/src/rules/frames.ts +4 -5
- package/packages/cli/src/commands/doctor.ts +15 -2
- package/packages/cli/src/commands/fonts.ts +118 -0
- package/packages/cli/src/commands/make.ts +15 -5
- package/packages/cli/src/commands/render.ts +34 -7
- package/packages/cli/src/commands/update.ts +66 -0
- package/packages/cli/src/fonts.ts +405 -0
- package/packages/cli/src/kf.ts +5 -0
- package/packages/cli/src/mix.ts +66 -4
- package/packages/cli/src/segments.ts +1 -1
- package/packages/cli/src/sfx.ts +429 -0
- package/packages/cli/src/update.ts +250 -0
- package/packages/core/src/frame.ts +7 -4
- package/packages/core/src/index.ts +3 -1
- package/packages/core/src/project.ts +19 -0
- package/packages/core/src/sfx.ts +70 -0
- package/packages/director/src/assemble.ts +7 -4
- package/packages/director/src/index.ts +1 -1
- package/packages/director/src/pattern.ts +2 -0
- package/packages/director/src/scene.ts +14 -5
- package/packages/director/src/transitions.ts +21 -8
- package/packages/motion/src/enter.ts +7 -1
- package/packages/motion/src/impact.ts +5 -2
- package/packages/motion/src/moves/dress.ts +15 -2
- package/packages/motion/src/moves/menu.ts +11 -5
- package/packages/motion/src/transition.ts +3 -1
- package/packages/motion/src/transition3d/index.ts +3 -1
- package/packages/motion/src/transition3d/live.ts +5 -3
- package/packages/patterns/src/bars/rank.ts +6 -7
- package/packages/patterns/src/before-after/shrink.ts +3 -4
- package/packages/patterns/src/before-after/strike.ts +4 -5
- package/packages/patterns/src/code/terminal.ts +25 -16
- package/packages/patterns/src/end/lockup.ts +13 -10
- package/packages/patterns/src/end/slam.ts +7 -5
- package/packages/patterns/src/hook-number/counter.ts +15 -9
- package/packages/patterns/src/hook-number/slam.ts +6 -8
- package/packages/patterns/src/kit.ts +281 -58
- package/packages/patterns/src/limit/gauge.ts +16 -11
- package/packages/patterns/src/quote/karaoke.ts +17 -12
- package/packages/patterns/src/sfx.ts +80 -0
- package/packages/patterns/src/term-reveal/chips.ts +24 -10
- package/packages/patterns/src/term-reveal/expand.ts +17 -13
- package/packages/patterns/src/title/mask.ts +9 -8
- package/packages/patterns/src/title/slam.ts +1 -1
- package/packages/patterns/src/types.ts +1 -0
- package/packages/plan/src/asks.ts +1 -1
- package/packages/plan/src/brief.ts +5 -2
- package/packages/plan/src/themes.ts +8 -2
- package/packages/themes/kit/THEME-MAKE.md +2 -2
- package/packages/themes/kit/fonts/display.json +3517 -0
- package/packages/themes/kit/fonts/sans.json +5155 -0
- package/packages/themes/kit/fonts/serif.json +5229 -0
- package/packages/themes/kit/fonts.json +243 -79
- package/packages/themes/package.json +3 -1
- package/packages/themes/src/fontfile.ts +183 -0
- package/packages/themes/src/fonts.ts +296 -0
- package/packages/themes/src/index.ts +32 -2
- package/packages/themes/src/look.ts +34 -8
- package/packages/themes/src/slots.ts +32 -2
- package/packages/themes/src/types.ts +33 -0
- package/packages/themes/src/vary.ts +35 -34
- package/presets/kawaii-pastel.json +2 -2
- package/sfx/README.md +82 -0
- package/sfx/click/appear.wav +0 -0
- package/sfx/click/burst.wav +0 -0
- package/sfx/click/drop.wav +0 -0
- package/sfx/click/end.wav +0 -0
- package/sfx/click/hop.wav +0 -0
- package/sfx/click/land.wav +0 -0
- package/sfx/click/select.wav +0 -0
- package/sfx/click/stick.wav +0 -0
- package/sfx/click/tick.wav +0 -0
- package/sfx/click/type.wav +0 -0
- package/sfx/click/whoosh.wav +0 -0
- package/sfx/pop/appear.wav +0 -0
- package/sfx/pop/burst.wav +0 -0
- package/sfx/pop/drop.wav +0 -0
- package/sfx/pop/end.wav +0 -0
- package/sfx/pop/hop.wav +0 -0
- package/sfx/pop/land.wav +0 -0
- package/sfx/pop/select.wav +0 -0
- package/sfx/pop/stick.wav +0 -0
- package/sfx/pop/tick.wav +0 -0
- package/sfx/pop/type.wav +0 -0
- package/sfx/pop/whoosh.wav +0 -0
- package/sfx/tags.json +545 -0
- package/sfx/ui/appear.wav +0 -0
- package/sfx/ui/burst.wav +0 -0
- package/sfx/ui/drop.wav +0 -0
- package/sfx/ui/end.wav +0 -0
- package/sfx/ui/hop.wav +0 -0
- package/sfx/ui/land.wav +0 -0
- package/sfx/ui/select.wav +0 -0
- package/sfx/ui/stick.wav +0 -0
- package/sfx/ui/tick.wav +0 -0
- package/sfx/ui/type.wav +0 -0
- package/sfx/ui/whoosh.wav +0 -0
- package/skills/kasaframe/SKILL.md +1 -0
- package/themes/blueprint/sample/style.json +5 -5
- package/themes/blueprint/style.json +5 -5
- package/themes/blueprint/theme.json +3 -1
- package/themes/blueprint/variants/deep-rose-suit.json +1 -1
- package/themes/blueprint/variants/navy-coral-2.json +1 -1
- package/themes/blueprint/variants/navy-coral-suit.json +1 -1
- package/themes/blueprint/variants/navy-orange-2.json +1 -1
- package/themes/blueprint/variants/navy-orange-suit.json +1 -1
- package/themes/cartography/sample/style.json +2 -2
- package/themes/cartography/style.json +2 -2
- package/themes/cartography/theme.json +3 -1
- package/themes/cartography/variants/deep-plum.json +1 -1
- package/themes/cartography/variants/frost-teal.json +1 -1
- package/themes/cartography/variants/navy-green.json +1 -1
- package/themes/circuit-board/sample/style.json +2 -2
- package/themes/circuit-board/style.json +2 -2
- package/themes/circuit-board/theme.json +3 -1
- package/themes/circuit-board/variants/dusk-gold-pretendard.json +1 -1
- package/themes/circuit-board/variants/navy-gold-grain.json +1 -1
- package/themes/circuit-board/variants/wine-gold-pretendard.json +1 -1
- package/themes/clay-toy/sample/style.json +2 -2
- package/themes/clay-toy/style.json +2 -2
- package/themes/clay-toy/theme.json +3 -1
- package/themes/clay-toy/variants/blush-coral-grain.json +1 -1
- package/themes/clay-toy/variants/chalk-teal.json +1 -1
- package/themes/clay-toy/variants/frost-sky.json +1 -1
- package/themes/clay-toy/variants/frost-teal.json +1 -1
- package/themes/clay-toy/variants/lilac-plum-round.json +1 -1
- package/themes/clay-toy/variants/lilac-plum.json +1 -1
- package/themes/clay-toy/variants/sage-indigo.json +1 -1
- package/themes/conveyor-factory/sample/style.json +3 -3
- package/themes/conveyor-factory/style.json +3 -3
- package/themes/conveyor-factory/theme.json +3 -1
- package/themes/conveyor-factory/variants/cocoa-gold.json +1 -1
- package/themes/conveyor-factory/variants/navy-gold.json +1 -1
- package/themes/conveyor-factory/variants/slate-amber-2.json +1 -1
- package/themes/conveyor-factory/variants/slate-amber-suit.json +1 -1
- package/themes/conveyor-factory/variants/slate-gold-bold.json +1 -1
- package/themes/data-journal/theme.json +3 -1
- package/themes/data-journal/variants/deep-coral.json +1 -1
- package/themes/data-journal/variants/navy-lime.json +1 -1
- package/themes/data-journal/variants/wine-indigo.json +1 -1
- package/themes/debug-hud/sample/style.json +1 -1
- package/themes/debug-hud/style.json +1 -1
- package/themes/debug-hud/theme.json +2 -1
- package/themes/debug-hud/variants/cocoa-teal.json +2 -2
- package/themes/debug-hud/variants/deep-teal-scan.json +2 -2
- package/themes/debug-hud/variants/dusk-plum.json +2 -2
- package/themes/debug-hud/variants/forest-lime.json +2 -2
- package/themes/debug-hud/variants/slate-green.json +2 -2
- package/themes/debug-hud/variants/wine-gold.json +2 -2
- package/themes/depth-flight/sample/style.json +1 -1
- package/themes/depth-flight/style.json +1 -1
- package/themes/depth-flight/theme.json +3 -1
- package/themes/depth-flight/variants/cocoa-cyan.json +1 -1
- package/themes/depth-flight/variants/cocoa-violet.json +1 -1
- package/themes/depth-flight/variants/deep-sky.json +1 -1
- package/themes/depth-flight/variants/forest-blue.json +1 -1
- package/themes/depth-flight/variants/navy-sky-grain.json +1 -1
- package/themes/depth-flight/variants/navy-sky.json +1 -1
- package/themes/depth-flight/variants/night-teal.json +1 -1
- package/themes/depth-flight/variants/slate-indigo.json +1 -1
- package/themes/depth-flight/variants/slate-violet.json +1 -1
- package/themes/film-reel/sample/style.json +2 -2
- package/themes/film-reel/style.json +2 -2
- package/themes/film-reel/theme.json +3 -1
- package/themes/film-reel/variants/chalk-pink.json +1 -1
- package/themes/film-reel/variants/lilac-gold.json +1 -1
- package/themes/film-reel/variants/lilac-violet.json +1 -1
- package/themes/glass-light/sample/style.json +1 -1
- package/themes/glass-light/style.json +1 -1
- package/themes/glass-light/theme.json +3 -1
- package/themes/glass-light/variants/blush-pink.json +1 -1
- package/themes/glass-light/variants/blush-plum.json +1 -1
- package/themes/glass-light/variants/cream-violet.json +1 -1
- package/themes/glass-light/variants/frost-sky-suit.json +1 -1
- package/themes/glass-light/variants/frost-sky.json +1 -1
- package/themes/glass-light/variants/sage-green.json +1 -1
- package/themes/ink-wash/sample/style.json +3 -3
- package/themes/ink-wash/style.json +3 -3
- package/themes/ink-wash/theme.json +3 -1
- package/themes/iso-diorama/sample/style.json +1 -1
- package/themes/iso-diorama/style.json +1 -1
- package/themes/iso-diorama/theme.json +3 -1
- package/themes/iso-diorama/variants/chalk-plum.json +1 -1
- package/themes/iso-diorama/variants/cocoa-indigo.json +1 -1
- package/themes/iso-diorama/variants/dusk-blue.json +1 -1
- package/themes/iso-diorama/variants/dusk-coral.json +1 -1
- package/themes/iso-diorama/variants/dusk-jade.json +1 -1
- package/themes/iso-diorama/variants/forest-cyan.json +1 -1
- package/themes/iso-diorama/variants/frost-green.json +1 -1
- package/themes/iso-diorama/variants/frost-teal.json +1 -1
- package/themes/iso-diorama/variants/navy-amber.json +1 -1
- package/themes/isotype/sample/style.json +2 -2
- package/themes/isotype/style.json +2 -2
- package/themes/isotype/theme.json +2 -1
- package/themes/isotype/variants/blush-rose.json +1 -1
- package/themes/isotype/variants/chalk-coral.json +1 -1
- package/themes/isotype/variants/chalk-orange.json +1 -1
- package/themes/isotype/variants/frost-amber.json +1 -1
- package/themes/isotype/variants/frost-coral.json +1 -1
- package/themes/isotype/variants/frost-orange.json +1 -1
- package/themes/isotype/variants/sand-amber.json +1 -1
- package/themes/kawaii-sticker/effects.ts +15 -3
- package/themes/kawaii-sticker/sample/style.json +2 -2
- package/themes/kawaii-sticker/style.json +2 -2
- package/themes/kawaii-sticker/theme.json +4 -1
- package/themes/kawaii-sticker/variants/cream-gold.json +1 -1
- package/themes/kawaii-sticker/variants/dusk-green.json +1 -1
- package/themes/kawaii-sticker/variants/dusk-indigo.json +1 -1
- package/themes/kawaii-sticker/variants/dusk-sky.json +1 -1
- package/themes/kawaii-sticker/variants/dusk-teal.json +1 -1
- package/themes/kawaii-sticker/variants/frost-blue.json +1 -1
- package/themes/kawaii-sticker/variants/frost-plum.json +1 -1
- package/themes/kawaii-sticker/variants/lilac-violet.json +1 -1
- package/themes/kawaii-sticker/variants/navy-gold.json +1 -1
- package/themes/kawaii-sticker/variants/navy-plum.json +1 -1
- package/themes/lab-notebook/sample/style.json +3 -3
- package/themes/lab-notebook/style.json +3 -3
- package/themes/lab-notebook/theme.json +2 -1
- package/themes/lab-notebook/variants/blush-orange.json +1 -1
- package/themes/lab-notebook/variants/chalk-coral.json +1 -1
- package/themes/lab-notebook/variants/chalk-orange.json +1 -1
- package/themes/lab-notebook/variants/chalk-rose.json +1 -1
- package/themes/lab-notebook/variants/lilac-rose.json +1 -1
- package/themes/lab-notebook/variants/sage-rose.json +1 -1
- package/themes/lab-notebook/variants/sand-orange.json +1 -1
- package/themes/lab-notebook/variants/snow-orange.json +1 -1
- package/themes/lab-notebook/variants/snow-rose.json +1 -1
- package/themes/manga-panel/sample/style.json +3 -3
- package/themes/manga-panel/style.json +3 -3
- package/themes/manga-panel/theme.json +3 -1
- package/themes/manga-panel/variants/chalk-cyan-dots.json +1 -1
- package/themes/manga-panel/variants/chalk-rose.json +1 -1
- package/themes/manga-panel/variants/snow-cyan.json +1 -1
- package/themes/manga-panel/variants/snow-magenta-dots.json +1 -1
- package/themes/marble-run/sample/style.json +2 -2
- package/themes/marble-run/style.json +2 -2
- package/themes/marble-run/theme.json +3 -1
- package/themes/marble-run/variants/slate-orange.json +1 -1
- package/themes/neon-sign/sample/style.json +2 -2
- package/themes/neon-sign/style.json +2 -2
- package/themes/neon-sign/theme.json +2 -1
- package/themes/neon-sign/variants/dusk-plum.json +1 -1
- package/themes/neon-sign/variants/forest-magenta.json +1 -1
- package/themes/neon-sign/variants/night-pink.json +1 -1
- package/themes/neon-sign/variants/night-violet.json +1 -1
- package/themes/neon-sign/variants/slate-violet.json +1 -1
- package/themes/newspaper/sample/style.json +2 -2
- package/themes/newspaper/style.json +2 -2
- package/themes/newspaper/theme.json +2 -1
- package/themes/newspaper/variants/blush-amber.json +1 -1
- package/themes/newspaper/variants/chalk-magenta.json +1 -1
- package/themes/newspaper/variants/frost-sky.json +1 -1
- package/themes/newspaper/variants/lilac-green.json +1 -1
- package/themes/newspaper/variants/sage-lime.json +1 -1
- package/themes/og-measure/THEME.md +41 -6
- package/themes/og-measure/effects.ts +236 -115
- package/themes/og-measure/sample/assets/brand/og-logo.svg +11 -11
- package/themes/og-measure/sample/lib/data.ts +6 -0
- package/themes/og-measure/sample/scenes/end.ts +14 -10
- package/themes/og-measure/sample/scenes/gather.ts +4 -1
- package/themes/og-measure/sample/scenes/models.ts +5 -2
- package/themes/og-measure/sample/scenes/one.ts +9 -6
- package/themes/og-measure/sample/scenes/price.ts +8 -3
- package/themes/og-measure/sample/style.json +30 -35
- package/themes/og-measure/slots.ts +54 -30
- package/themes/og-measure/still.png +0 -0
- package/themes/og-measure/style.json +30 -35
- package/themes/og-measure/theme.json +72 -49
- package/themes/og-measure/variants/snow-blue.json +90 -0
- package/themes/orbit-system/sample/style.json +3 -3
- package/themes/orbit-system/style.json +3 -3
- package/themes/orbit-system/theme.json +3 -1
- package/themes/orbit-system/variants/cocoa-amber.json +1 -1
- package/themes/orbit-system/variants/cocoa-cyan.json +1 -1
- package/themes/orbit-system/variants/dusk-magenta.json +1 -1
- package/themes/orbit-system/variants/dusk-violet.json +1 -1
- package/themes/orbit-system/variants/forest-coral.json +1 -1
- package/themes/orbit-system/variants/wine-amber.json +1 -1
- package/themes/orbit-system/variants/wine-magenta.json +1 -1
- package/themes/origami-fold/sample/style.json +1 -1
- package/themes/origami-fold/style.json +1 -1
- package/themes/origami-fold/theme.json +3 -1
- package/themes/origami-fold/variants/deep-amber-sunflower.json +1 -1
- package/themes/origami-fold/variants/deep-orange.json +1 -1
- package/themes/origami-fold/variants/forest-coral.json +1 -1
- package/themes/origami-fold/variants/forest-pink.json +1 -1
- package/themes/origami-fold/variants/frost-amber-paper.json +1 -1
- package/themes/origami-fold/variants/sage-coral-sunflower.json +1 -1
- package/themes/origami-fold/variants/sage-coral.json +1 -1
- package/themes/origami-fold/variants/sage-pink-round.json +1 -1
- package/themes/origami-fold/variants/sage-pink.json +1 -1
- package/themes/paper-cutout/sample/style.json +2 -2
- package/themes/paper-cutout/style.json +2 -2
- package/themes/paper-cutout/theme.json +3 -1
- package/themes/paper-cutout/variants/blush-violet.json +1 -1
- package/themes/paper-cutout/variants/frost-lime.json +1 -1
- package/themes/paper-cutout/variants/lilac-gold.json +1 -1
- package/themes/paper-cutout/variants/sage-cyan.json +1 -1
- package/themes/paper-cutout/variants/sage-green.json +1 -1
- package/themes/paper-cutout/variants/sage-pink.json +1 -1
- package/themes/paper-cutout/variants/sand-blue.json +1 -1
- package/themes/pixel-quest/theme.json +2 -1
- package/themes/receipt/sample/style.json +2 -2
- package/themes/receipt/style.json +2 -2
- package/themes/riso-zine/sample/style.json +2 -2
- package/themes/riso-zine/style.json +2 -2
- package/themes/riso-zine/theme.json +3 -1
- package/themes/riso-zine/variants/chalk-lime.json +1 -1
- package/themes/riso-zine/variants/frost-green.json +1 -1
- package/themes/riso-zine/variants/lilac-plum.json +1 -1
- package/themes/riso-zine/variants/lilac-violet.json +1 -1
- package/themes/server-hall/sample/style.json +2 -2
- package/themes/server-hall/style.json +2 -2
- package/themes/server-hall/theme.json +3 -1
- package/themes/server-hall/variants/night-indigo.json +1 -1
- package/themes/server-hall/variants/wine-plum.json +1 -1
- package/themes/subway-map/sample/style.json +2 -2
- package/themes/subway-map/style.json +2 -2
- package/themes/subway-map/theme.json +3 -1
- package/themes/subway-map/variants/deep-green.json +1 -1
- package/themes/subway-map/variants/deep-teal.json +1 -1
- package/themes/subway-map/variants/frost-jade.json +1 -1
- package/themes/subway-map/variants/frost-teal.json +1 -1
- package/themes/subway-map/variants/slate-green.json +1 -1
- package/themes/subway-map/variants/snow-jade.json +1 -1
- package/themes/swiss-poster/sample/style.json +2 -2
- package/themes/swiss-poster/style.json +2 -2
- package/themes/swiss-poster/theme.json +3 -1
- package/themes/swiss-poster/variants/chalk-plum.json +1 -1
- package/themes/swiss-poster/variants/cocoa-cyan.json +1 -1
- package/themes/swiss-poster/variants/dusk-magenta.json +1 -1
- package/themes/swiss-poster/variants/frost-indigo.json +1 -1
- package/themes/swiss-poster/variants/slate-orange.json +1 -1
- package/themes/water-works/sample/style.json +1 -1
- package/themes/water-works/style.json +1 -1
- package/themes/water-works/theme.json +3 -1
- package/themes/water-works/variants/chalk-cyan.json +1 -1
- package/themes/water-works/variants/frost-indigo.json +1 -1
- package/themes/water-works/variants/sand-amber.json +1 -1
- package/themes/water-works/variants/sand-plum.json +1 -1
- package/themes/whiteboard/sample/style.json +2 -2
- package/themes/whiteboard/style.json +2 -2
- package/themes/whiteboard/theme.json +3 -1
- package/themes/whiteboard/variants/chalk-coral.json +1 -1
- package/themes/whiteboard/variants/cream-lime.json +1 -1
- package/themes/whiteboard/variants/frost-teal.json +1 -1
- package/themes/whiteboard/variants/lilac-indigo.json +1 -1
- package/themes/whiteboard/variants/sage-plum.json +1 -1
- package/themes/whiteboard/variants/snow-cyan.json +1 -1
- package/themes/whiteboard/variants/snow-green.json +1 -1
- package/themes/whiteboard/variants/snow-magenta.json +1 -1
- package/themes/og-measure/sample/assets/brand/og-logo-full.svg +0 -12
- package/themes/og-measure/variants/chalk-orange.json +0 -102
- package/themes/og-measure/variants/cocoa-amber.json +0 -138
- package/themes/og-measure/variants/cocoa-cyan.json +0 -138
- package/themes/og-measure/variants/cocoa-gold.json +0 -129
- package/themes/og-measure/variants/cream-lime.json +0 -137
- package/themes/og-measure/variants/deep-jade.json +0 -100
- package/themes/og-measure/variants/dusk-violet.json +0 -133
- package/themes/og-measure/variants/forest-cyan.json +0 -123
- package/themes/og-measure/variants/frost-amber.json +0 -129
- package/themes/og-measure/variants/frost-cyan.json +0 -133
- package/themes/og-measure/variants/lilac-plum.json +0 -127
- package/themes/og-measure/variants/lilac-violet.json +0 -139
- package/themes/og-measure/variants/sage-green.json +0 -137
- package/themes/og-measure/variants/wine-jade.json +0 -127
- package/themes/og-measure/variants/wine-plum.json +0 -127
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { type FontPair, fontGroups, fontPairs } from "@kasaframe/themes/fonts";
|
|
7
|
+
import { type Command, parseFlags } from "../command.ts";
|
|
8
|
+
import { checkFonts, fontCacheDir, fontSheet, noticeSection, type PairReport, replaceNotice } from "../fonts.ts";
|
|
9
|
+
|
|
10
|
+
const cmd: Command = {
|
|
11
|
+
summary: "๊ธ๊ผด ์ง ๊ฒ์ฌยท๊ฒฌ๋ณธ ๊ฒฉ์ โ ์ฃผ์ยทํยท๋ผ์ด์ ์ค ๊ธยทํ๊ธ ๋ฎ์ยท๊ตต๊ธฐ, ํฌ๋กฌ์ผ๋ก ์ฐ์ด ํฌ๋ช
ยท๋๋ถยท๋จ์ด์ง",
|
|
12
|
+
usage: `kf fonts list [--group <๋ฌด๋ฆฌ>]
|
|
13
|
+
kf fonts check [--group <๋ฌด๋ฆฌ>[,โฆ]] [--id <์ง>[,โฆ]] [--json] [--no-render] [--offline]
|
|
14
|
+
kf fonts sheet [--group <๋ฌด๋ฆฌ>[,โฆ]] [--id <์ง>[,โฆ]] [--out ํ์ผ.png] [--share]
|
|
15
|
+
kf fonts notice [--write]
|
|
16
|
+
|
|
17
|
+
์ง ๋ชฉ๋ก์ packages/themes/kit/fonts.json(๋ฌด๋ฆฌ core)๊ณผ kit/fonts/<๋ฌด๋ฆฌ>.json ์ ํฉ์น ๊ฒ.
|
|
18
|
+
check ๋ ์ง๋ง๋ค
|
|
19
|
+
- ์นธ: hangul(full|ks2350)ยทface ๋ง๋ค licenseยทsource, ์คํ ์ฒซ ๊ธ๊ผด์ face, ๋ชจ๋ ์คํ์ด Pretendard Variable ๋ก ๋๋จ
|
|
20
|
+
- ์ฃผ์: ํ์ผยท๋ผ์ด์ ์ค ๊ธ์ด 200, ํ ๋ฐํ(jsdelivr gh@์ปค๋ฐ|ํ๊ทธยทnpm@x.y.z โ @mainยท@latestยท@5 ๋ ์ ๋๋ค)
|
|
21
|
+
- ๋ผ์ด์ ์ค ๊ธ: OFL-1.1ยทApache-2.0 ์ ๊ธ์ ๊ทธ ๋ฌธ๊ตฌ๊ฐ ์๋์ง. ๋ชฉ๋ก ๋ฐ ์ด๋ฆ์ ์ฌ๋์ด ์ฝ์ ๊ฒ์ผ๋ก ๋จ๊ธด๋ค
|
|
22
|
+
- ํ์ผ: ํ๊ธ ์์ ์(11,172 = full, KS X 1001 2,350 ๋ค = ks2350, ๊ทธ ์๋๋ ํ๋ฝ)์ ์ ์ hangul ์ด ๋ง๋์ง,
|
|
23
|
+
์ ์ ๊ตต๊ธฐ ๋ฒ์๊ฐ ํ์ผ(wght ์ถยทusWeightClass)๊ณผ ๋ง๋์ง, ์ ๋ชฉ ๊ตต๊ธฐ ๋จ์ด ์๋์ง(์์ผ๋ฉด ๊ฐ์ง ๊ตต๊ธฐ)
|
|
24
|
+
- ํฌ๋กฌ: ์คํ๋ง๋ค ํ๊ธยท๋ผํดยท์ซ์ ๊ฒฌ๋ณธ ํ ์ค์ ์ฐ์ด ํฌ๋ช
ยท๋๋ถยท์์คํ
๊ธ๊ผด๋ก ๋จ์ด์งยท์์๊ณผ ๋ค๋ฅธ face ๋ฅผ ์ก๋๋ค
|
|
25
|
+
๋ฐ์ ํ์ผ์ ${fontCacheDir()}/files ์ ๋๊ณ ๋ค์๋ถํฐ๋ ์ฃผ์๊ฐ ์ด์๋์ง๋ง ๋ฌป๋๋ค. ๋ฌธ์ ๊ฐ ์๋ ์ง์ด ์์ผ๋ฉด ์ข
๋ฃ 1.
|
|
26
|
+
--json { pairs: [{ id, group, ok, hangul, syllables, boldest, licenses, problems, notes }], summary }
|
|
27
|
+
--no-render ํฌ๋กฌ ์์ด(ํ์ผยท์ฃผ์๋ง)
|
|
28
|
+
--offline ์ฃผ์๋ฅผ ๋ฌป์ง ์๊ณ ์บ์๋ง(๋ผ์ด์ ์ค ๊ธ ๋์กฐ๋ ๊ฑด๋๋ด๋ค)
|
|
29
|
+
sheet ๋ ์ง๋ง๋ค ์ ๋ชฉยท๋ณธ๋ฌธยท๊ณ ์ ํญ ๊ฒฌ๋ณธ ์นธ์ ๊ฒฉ์ ํ ์ฅ์ผ๋ก โ ๊ธฐ๋ณธ ${fontCacheDir()}/sheet[-<๋ฌด๋ฆฌ>].png.
|
|
30
|
+
--share ๋ฉด kasaterm ๊ณต์ ํด๋ kasaframe-๊ธ๊ผด ๋ก ์ฎ๊ธด๋ค.
|
|
31
|
+
notice ๋ ๋ชจ๋ ๋ฌด๋ฆฌ๋ฅผ ํฉ์น ๋ชฉ๋ก์ผ๋ก NOTICE ์ ๊ธ๊ผด ์ (๊ธ๊ผด ์ด๋ฆ ยท ๋ผ์ด์ ์ค ยท ๋ผ์ด์ ์ค ๊ธ)์ ์ฐ๋๋ค. --write ๋ฉด ๋ ํฌ NOTICE ์
|
|
32
|
+
๊ทธ ์ ์ ๊ฐ์ ๋ผ์ด๋ค โ ๋ฌด๋ฆฌ ํ์ผ์ ๊ณ ์น ๋ค ํ ๋ฒ.`,
|
|
33
|
+
async run(argv) {
|
|
34
|
+
const [sub, ...rest] = argv;
|
|
35
|
+
const { opts } = parseFlags(rest);
|
|
36
|
+
const list = pick(opts);
|
|
37
|
+
if (!list) return 2;
|
|
38
|
+
if (sub === "list" || !sub) {
|
|
39
|
+
for (const { group, pair } of list) console.log(`${group.padEnd(10)} ${pair.id.padEnd(26)} ${String(pair.hangul ?? "?").padEnd(7)} ${pair.tags.join(",").padEnd(30)} ${pair.name}`);
|
|
40
|
+
console.log(`์ง ${list.length}`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
if (sub === "check") {
|
|
44
|
+
const reports = await checkFonts(list, { offline: !!opts.offline, render: !opts["no-render"], log: (l) => console.error(l) });
|
|
45
|
+
const summary = summarize(reports);
|
|
46
|
+
if (opts.json) console.log(JSON.stringify({ pairs: reports, summary }, null, 1));
|
|
47
|
+
else print(reports, summary);
|
|
48
|
+
return reports.every((r) => r.ok) ? 0 : 1;
|
|
49
|
+
}
|
|
50
|
+
if (sub === "notice") {
|
|
51
|
+
const section = noticeSection(fontPairs());
|
|
52
|
+
if (!opts.write) {
|
|
53
|
+
process.stdout.write(section);
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
const file = fileURLToPath(new URL("../../../../NOTICE", import.meta.url));
|
|
57
|
+
writeFileSync(file, replaceNotice(readFileSync(file, "utf8"), section));
|
|
58
|
+
console.log(file);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
if (sub === "sheet") {
|
|
62
|
+
const groups = typeof opts.group === "string" ? opts.group.replace(/,/g, "+") : "";
|
|
63
|
+
const out = resolve(typeof opts.out === "string" ? opts.out : join(fontCacheDir(), `sheet${groups ? `-${groups}` : ""}.png`));
|
|
64
|
+
await fontSheet(list, out, { log: (l) => console.error(l) });
|
|
65
|
+
console.log(out);
|
|
66
|
+
if (opts.share) {
|
|
67
|
+
const r = spawnSync("kasaterm-cli", ["share", "new", "kasaframe-๊ธ๊ผด"], { encoding: "utf8" });
|
|
68
|
+
let dir = r.status === 0 ? (r.stdout.trim().split("\n").pop() ?? "") : "";
|
|
69
|
+
if (!dir || !existsSync(dir)) {
|
|
70
|
+
dir = join(homedir(), "Desktop", "kasaframe-๊ธ๊ผด");
|
|
71
|
+
mkdirSync(dir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
copyFileSync(out, join(dir, basename(out)));
|
|
74
|
+
console.log(`๊ณต์ ํด๋ ${dir}`);
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
console.error(`kf fonts: ๋ชจ๋ฅด๋ ํ์ ๋ช
๋ น ${sub} โ listยทcheckยทsheetยทnotice`);
|
|
79
|
+
return 2;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
function pick(opts: Record<string, string | boolean | undefined>): { group: string; pair: FontPair }[] | null {
|
|
84
|
+
const groups = fontGroups();
|
|
85
|
+
const want = typeof opts.group === "string" ? opts.group.split(",") : null;
|
|
86
|
+
const unknown = want?.filter((g) => !groups.some((x) => x.group === g));
|
|
87
|
+
if (unknown?.length) {
|
|
88
|
+
console.error(`kf fonts: ๋ฌด๋ฆฌ ${unknown.join(",")} ๊ฐ ์๋ค โ ์๋ ๋ฌด๋ฆฌ: ${groups.map((g) => g.group).join(" ")}`);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const ids = typeof opts.id === "string" ? new Set(opts.id.split(",")) : null;
|
|
92
|
+
const list = groups.filter((g) => !want || want.includes(g.group)).flatMap((g) => g.pairs.map((pair) => ({ group: g.group, pair }))).filter(({ pair }) => !ids || ids.has(pair.id));
|
|
93
|
+
if (ids && list.length < ids.size) console.error(`kf fonts: ์๋ ์ง โ ${[...ids].filter((i) => !list.some((x) => x.pair.id === i)).join(",")}`);
|
|
94
|
+
return list;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const tally = (xs: string[]) => Object.fromEntries([...new Set(xs)].sort().map((x) => [x, xs.filter((y) => y === x).length]));
|
|
98
|
+
|
|
99
|
+
function summarize(reports: PairReport[]) {
|
|
100
|
+
return {
|
|
101
|
+
pairs: reports.length,
|
|
102
|
+
ok: reports.filter((r) => r.ok).length,
|
|
103
|
+
hangul: tally(reports.map((r) => r.hangul ?? "?")),
|
|
104
|
+
licenses: tally(reports.flatMap((r) => r.licenses)),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function print(reports: PairReport[], s: ReturnType<typeof summarize>): void {
|
|
109
|
+
for (const r of reports) {
|
|
110
|
+
console.log(`${r.ok ? "ok " : "๋ฌธ์ "} ${r.group.padEnd(10)} ${r.id.padEnd(26)} ํ๊ธ ${r.hangul ?? "?"}(${r.syllables ?? "?"}) ยท ๊ตต์ ๋จ ${r.boldest ?? "?"} ยท ${r.licenses.join(",")}`);
|
|
111
|
+
for (const p of r.problems) console.log(` ! ${p}`);
|
|
112
|
+
for (const n of r.notes) console.log(` ยท ${n}`);
|
|
113
|
+
}
|
|
114
|
+
const fmt = (o: Record<string, number>) => Object.entries(o).map(([k, v]) => `${k} ${v}`).join(" ยท ");
|
|
115
|
+
console.log(`\n์ง ${s.pairs} โ ํต๊ณผ ${s.ok} ยท ๋ฌธ์ ${s.pairs - s.ok} | ํ๊ธ ${fmt(s.hangul)} | ๋ผ์ด์ ์ค(์ง ๊ธฐ์ค) ${fmt(s.licenses)}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export default cmd;
|
|
@@ -103,6 +103,7 @@ kf make --answer <ํด๋> --image <๊ฐ> --video <๊ฐ> โฆ Claude Code ๋ชจ๋
|
|
|
103
103
|
--video-provider ์์ ๊ณต๊ธ์๋ฅผ ๋ชป ๋ฐ๋๋ค(์: h3-pod โ KF_H3_URLยทKF_H3_STEPS ํ์). ๊ธฐ๋ณธ์ KF_VIDEO_PROVIDER, ์์ผ๋ฉด ์์ฑ ๋ด๋น ๊ธฐ๋ณธ
|
|
104
104
|
--fix ๊ฒ์ฌ๊ฐ ๋จ์ด์ก์ ๋ ๊ณ ์น๊ธฐ ํ์(๊ธฐ๋ณธ 2)
|
|
105
105
|
--captions on|off|fit ํ๋ฉด ์๋ง(fit ์ ์ฅ๋ฉด์ ์๋ง ๋ ์๋ก ์ค์ฌ ์ฌ๋ฆฐ๋ค) โ ์๋ก ๋ง๋ค ๋ kf.json ์ ์ ๊ณ , --finish ์์ ๊ทธ ํ๋ง ๋ฎ๋๋ค(๋ค์ ๋ง๋ค์ง ์๊ณ ์ผ๊ณ ๋๊ธฐ). srtยทvtt ๋ ๋ ๋ค ๋ธ๋ค
|
|
106
|
+
--sfx on|off ํจ๊ณผ์(๊ธฐ๋ณธ ์ผฌ โ ํ
๋ง๊ฐ ๊ณ ๋ฅธ ๊ฒฐ๋ก ์ฅ๋ฉด ์์ง์ ์๋ฆฌ์ ๊ณก ์๋ ์๊ฒ) โ ์๋ก ๋ง๋ค ๋ off ๋ฅผ kf.json ์ sfx: false ๋ก ์ ๊ณ , --finish ์์ ๊ทธ ํ๋ง ๋ฎ๋๋ค
|
|
106
107
|
--suffix [๊ธ] --finish ๊ฒฐ๊ณผ ์ด๋ฆ ๋ค์ ๋ถ์ธ๋ค(๊ฐ ์์ด๋ฉด -์๋ง ยท -์๋ง์์) โ ์๋ณธ video.mp4 ๋ฅผ ๋ฎ์ง ์๊ณ ๋ ๋ค ๋จ๊ธด๋ค
|
|
107
108
|
--no-gen ์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฅด์ง ์๋๋ค โ ๋ฌป์ง ์๊ณ ๊ทธ๋ฆผยท์์ ๋ชจ๋ธ์ ๋นผ๊ณ , Blender ๊ฐ ์์ผ๋ฉด three ๋ก ๋์ ํ๋ค
|
|
108
109
|
|
|
@@ -171,6 +172,11 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
171
172
|
return 2;
|
|
172
173
|
}
|
|
173
174
|
const suffix = str("suffix") ?? (opts.suffix ? (captions === "off" ? "-์๋ง์์" : "-์๋ง") : "");
|
|
175
|
+
const sfx = str("sfx");
|
|
176
|
+
if (sfx !== undefined && sfx !== "on" && sfx !== "off") {
|
|
177
|
+
console.error(`kf make: --sfx ๋ onยทoff โ ${sfx}`);
|
|
178
|
+
return 2;
|
|
179
|
+
}
|
|
174
180
|
|
|
175
181
|
if (opts.answer) {
|
|
176
182
|
at.quiet = true;
|
|
@@ -192,7 +198,7 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
192
198
|
const narrate = sayChanged(dir, ids) ? [] : ["--no-narrate"];
|
|
193
199
|
const d = await relay(["direct", dir, "--scenes", ids.join(","), ...narrate, "--no-check", ...pick]);
|
|
194
200
|
if (d !== 0) return d;
|
|
195
|
-
return finish(dir, { model: "direct", vision, fixes: 0, scenes: ids });
|
|
201
|
+
return finish(dir, { model: "direct", vision, fixes: 0, scenes: ids, sfx });
|
|
196
202
|
}
|
|
197
203
|
// ๋ค์ ์ฐ๊ธฐ๋ ๊ทธ ์ผ์ ๋ง๋ ๋ชจ๋ธ๋ก โ ๊ธฐ๋ณธ ๋ชจ๋ธ๋ก ๋ชฐ๋ ๋ฐ๊พธ์ง ์๋๋ค
|
|
198
204
|
const own = str("model") ?? readPlan(dir).model;
|
|
@@ -208,7 +214,7 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
208
214
|
}
|
|
209
215
|
writeFileSync(join(dir, "MAKE.md"), projectBrief(dir));
|
|
210
216
|
await writeScenes(dir, own, ids);
|
|
211
|
-
return finish(dir, { model: own, vision, fixes, scenes: ids });
|
|
217
|
+
return finish(dir, { model: own, vision, fixes, scenes: ids, sfx });
|
|
212
218
|
}
|
|
213
219
|
if (opts.finish) {
|
|
214
220
|
const dir = resolve(typeof opts.finish === "string" ? opts.finish : (args[0] ?? "."));
|
|
@@ -220,7 +226,7 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
220
226
|
if (studio) console.log(`์์
์ค: ${studio.url}`);
|
|
221
227
|
await studio?.send({ phase: "render" });
|
|
222
228
|
const scenes = str("scenes")?.split(",").filter(Boolean);
|
|
223
|
-
const code = await finish(dir, { model, vision, fixes, gen: opts["no-gen"] ? undefined : gen, captions, suffix, ...(scenes?.length ? { scenes } : {}) });
|
|
229
|
+
const code = await finish(dir, { model, vision, fixes, gen: opts["no-gen"] ? undefined : gen, captions, suffix, sfx, ...(scenes?.length ? { scenes } : {}) });
|
|
224
230
|
await unmirror?.();
|
|
225
231
|
await studio?.send({ done: true, ok: code === 0 });
|
|
226
232
|
return code;
|
|
@@ -352,6 +358,10 @@ async function make(argv: string[], at: Track): Promise<number> {
|
|
|
352
358
|
writeJson(kfPath, { ...JSON.parse(readFileSync(kfPath, "utf8")), captions });
|
|
353
359
|
plan.captions = captionMode(captions);
|
|
354
360
|
}
|
|
361
|
+
if (sfx === "off") {
|
|
362
|
+
const kfPath = join(dir, "kf.json");
|
|
363
|
+
writeJson(kfPath, { ...JSON.parse(readFileSync(kfPath, "utf8")), sfx: false });
|
|
364
|
+
}
|
|
355
365
|
if (!str("purpose") && !series) {
|
|
356
366
|
plan.confidence = chosen?.p ?? det.confidence;
|
|
357
367
|
plan.alternatives = det.ranked.filter((r) => r.purpose !== purpose).slice(0, 2).map((r) => ({ purpose: r.purpose, p: r.p }));
|
|
@@ -901,7 +911,7 @@ async function seamStills(dir: string, only?: string[]): Promise<void> {
|
|
|
901
911
|
|
|
902
912
|
// captions ๋ฅผ ์ฃผ๋ฉด ๊ทธ ํ๋ง ํ๋ฉด ์๋ง์ ์ผ๊ณ ๋๋ค(kf.json ์ ๊ทธ๋๋ก) โ ๊ตฝ๊ธฐยท๊ฒ์ฌยท์๋ง ํธ๋์ด ๊ฐ์ ๊ฐ์ ๋ณธ๋ค
|
|
903
913
|
// scenes ๋ฅผ ์ฃผ๋ฉด ๊ทธ ์ฅ๋ฉด ๋๋ (๊ทธ ์ฅ๋ฉด + ๋ถ์ ์ด์๋งค)๋ง โ ์ด์ ํ๋ฉดยท๊ฒ์ฌ๋ฅผ ๊ทธ ๊ตฌ๊ฐ์์. ๊ตฝ๊ธฐ๋ kf render ๊ฐ ๋ฐ๋ ์กฐ๊ฐ๋ง ๋ค์ ์ฐ๋๋ค
|
|
904
|
-
async function finish(dir: string, o: { model: string; vision: string; fixes: number; gen?: GenOpts; captions?: "on" | "off" | "fit"; suffix?: string; scenes?: string[] }): Promise<number> {
|
|
914
|
+
async function finish(dir: string, o: { model: string; vision: string; fixes: number; gen?: GenOpts; captions?: "on" | "off" | "fit"; suffix?: string; scenes?: string[]; sfx?: string }): Promise<number> {
|
|
905
915
|
if (!existsSync(join(dir, "kf.json"))) {
|
|
906
916
|
console.error(`kf make: ${dir} ์ kf.json ์ด ์๋ค`);
|
|
907
917
|
return 2;
|
|
@@ -921,7 +931,7 @@ async function finish(dir: string, o: { model: string; vision: string; fixes: nu
|
|
|
921
931
|
if (round > 0) await seamStills(dir, touched);
|
|
922
932
|
// ๊ตฝ๊ธฐ์ ๊ฒ์ฌ ์ฌ์ด์ ์ ๊ธ์ ๋์ผ๋ฉด ๊ธฐ๋ค๋ฆฌ๋ ๋จ์ ๊ธด ๋ ๋๊ฐ ๋ผ์ด๋ ๋ค โ ๋์ ํ ๋ฒ์ ์ฅ๊ณ ์์์ ์ ๊ธ ์์ด
|
|
923
933
|
const release = await acquireRenderLock(dir, 3600);
|
|
924
|
-
const r = await relay(["render", dir, "--out", out, "--tabs", "2", "--no-lock", ...capFlag]);
|
|
934
|
+
const r = await relay(["render", dir, "--out", out, "--tabs", "2", "--no-lock", ...capFlag, ...(o.sfx ? ["--sfx", o.sfx] : [])]);
|
|
925
935
|
if (r !== 0) {
|
|
926
936
|
release();
|
|
927
937
|
console.error("kf make: ๋ ๋๊ฐ ์คํจํ๋ค");
|
|
@@ -8,7 +8,8 @@ import { acquireRenderLock } from "../lock.ts";
|
|
|
8
8
|
import { blurOpts, captureBlurred, projectBlur, rgbaToPng } from "../blur.ts";
|
|
9
9
|
import { outPath } from "../out.ts";
|
|
10
10
|
import { cachedSegment, collectEvents, type KeyOpts, type MotionEvent, pruneSegments, renderSegments, sceneKeys, sceneSpans, type SegmentReport, type SegmentWork, variantOf } from "../segments.ts";
|
|
11
|
-
import { mixAudio, mixSettings } from "../mix.ts";
|
|
11
|
+
import { mixAudio, mixSettings, SFX_AUDIO, type SfxMix } from "../mix.ts";
|
|
12
|
+
import { cuesOf, loadBank, placeSfx, projectDrops, sfxSettings } from "../sfx.ts";
|
|
12
13
|
|
|
13
14
|
const MAX_TABS = 3;
|
|
14
15
|
|
|
@@ -61,7 +62,7 @@ function withSuffix(p: string, suffix: string): string {
|
|
|
61
62
|
|
|
62
63
|
const cmd: Command = {
|
|
63
64
|
summary: "MP4(๋๋ ProResยทPNG ๋ฌถ์)๋ก ๊ตฝ๊ธฐ โ ํญ ๋ณ๋ ฌ, ๊ณก ์น๊ธฐ, ์ ๊ธ",
|
|
64
|
-
usage: `kf render <ํด๋> [--out x.mp4] [--scenes a,b] [--from ์ด --to ์ด] [--tabs 3] [--prores | --png] [--music ๊ณก | --no-music] [--captions on|off|fit [--suffix]]
|
|
65
|
+
usage: `kf render <ํด๋> [--out x.mp4] [--scenes a,b] [--from ์ด --to ์ด] [--tabs 3] [--prores | --png] [--music ๊ณก | --no-music] [--sfx on|off] [--captions on|off|fit [--suffix]]
|
|
65
66
|
--out ๊ธฐ๋ณธ <ํด๋>/out/render.mp4 (--prores ๋ฉด .mov, --png ๋ฉด ํด๋)
|
|
66
67
|
seek ๋ชจ๋๋ ์ฅ๋ฉด ์กฐ๊ฐ์ผ๋ก ๊ตฝ๋๋ค โ ์ฅ๋ฉด๋ง๋ค out/segments/<์ฅ๋ฉด>-<ํด์>.mp4(ํด์: ๊ทธ ์ฅ๋ฉด์ด ์ค์ ๋ก ๋ถ๋ฌ์จ ๋ชจ๋ยทkf.json ๊ทธ ์ฅ๋ฉด ์นธยท
|
|
67
68
|
์์ฐยท์๋ง ์คยท๊ตฝ๊ธฐ ์ค์ , ์ด์๋งค๋ ์๋ค ์ฅ๋ฉด๊น์ง). ํด์๊ฐ ๊ฐ์ ์กฐ๊ฐ์ ๋ค์ ์ฐ์ง ์๊ณ ์ด์ด ๋ถ์ธ ๋ค ๊ณกยท๋ชฉ์๋ฆฌ๋ฅผ ์ ์ฒด๋ก ์น๋๋ค
|
|
@@ -71,6 +72,8 @@ const cmd: Command = {
|
|
|
71
72
|
--tabs ํฌ๋กฌ ํญ ์(์ต๋ ${MAX_TABS}). seek ๋ชจ๋๋ ๊ตฌ๊ฐ์ ๋๋ ์ฐ๊ณ , step ๋ชจ๋๋ ํญ๋ง๋ค ๊ตฌ๊ฐ ์๊น์ง ๋นจ๋ฆฌ ๋๋ฆฐ ๋ค ์ฐ๋๋ค
|
|
72
73
|
--music ๊ธฐ๋ณธ์ ํ์ด์ง meta.music(kf.json ์ music). ๊ณก์ beats.json ์ from ์ด๋ถํฐ ์น๋๋ค
|
|
73
74
|
--music-from ๊ณก์์ ์์ํ ์ด๋ฅผ ์ง์ ์ค๋ค(--music ์ผ๋ก ๋ค๋ฅธ ๊ณก์ ์ค ๋)
|
|
75
|
+
--sfx on|off ํจ๊ณผ์(๊ธฐ๋ณธ ์ผฌ) โ ์ฅ๋ฉด ์์ง์์ด ๋จ๊ธด ์๋ฆฌ ์๋ฆฌ(__kf.events ์ sfx)์ ๊ณก์ ๋๋กญ์ ํ
๋ง๊ฐ ๊ณ ๋ฅธ ๊ฒฐ(theme.json sfx)์ ์๋ฆฌ๋ฅผ
|
|
76
|
+
๊ณก ์๋๋ก ์๊ฒ ๊น๋ค. off ๋ฉด ์ด ํ๋ง ๋๊ณ (ํจ๊ณผ์ ์ด์ ๊ณผ ๊ฐ์ ์๋ฆฌ), on ์ด๋ฉด kf.json sfx: false ๋ ์ด ํ๋ง ์ผ ๋ค. --no-music ์ด๋ฉด ์๋ค
|
|
74
77
|
--crf H.264 ํ์ง(๊ธฐ๋ณธ 16, ๋ฎ์์๋ก ์ข๋ค)
|
|
75
78
|
--motion-blur N ํ ํ๋ ์์ ํ์ ํ๋ ์ N ์ฅ(์ 8)์ผ๋ก ์ฐ์ด ํ๊ท โ ๋น ๋ฅธ ๊ฒ๋ง ๋ฒ์ง๋ค. 3D ์ ํ์ ๊ฐ์ ํ๊ท ์ผ๋ก ํผ์ฌ๊ณ ์ฌ๋๋. seek ๋ชจ๋๋ง, N ๋ฐฐ ๋๋ฆฌ๋ค.
|
|
76
79
|
์ ์ฃผ๋ฉด kf.json ์ render.motionBlur(์ผ์ธ ยทํ๋ณด ํ์ ์ผ ๋๋ค), 0 ์ด๋ฉด ๋๋ค
|
|
@@ -91,6 +94,8 @@ const cmd: Command = {
|
|
|
91
94
|
const format: VideoFormat | "png" = opts.png ? "png" : opts.prores ? "prores" : "h264";
|
|
92
95
|
const ext = format === "prores" ? ".mov" : format === "png" ? "" : ".mp4";
|
|
93
96
|
const captions = opts.captions === undefined ? undefined : String(opts.captions);
|
|
97
|
+
const sfxFlag = opts.sfx === undefined ? undefined : String(opts.sfx);
|
|
98
|
+
if (sfxFlag !== undefined && sfxFlag !== "on" && sfxFlag !== "off") throw new Error(`--sfx ๋ onยทoff: ${sfxFlag}`);
|
|
94
99
|
if (captions !== undefined && captions !== "on" && captions !== "off" && captions !== "fit") throw new Error(`--captions ๋ onยทoffยทfit: ${captions}`);
|
|
95
100
|
const suffix = typeof opts.suffix === "string" ? opts.suffix : opts.suffix ? (captions === "off" ? "-์๋ง์์" : "-์๋ง") : "";
|
|
96
101
|
const out = withSuffix(outPath(dir, opts.out, format === "png" ? "frames/x" : `render${ext}`).replace(/\/x$/, ""), suffix);
|
|
@@ -139,6 +144,8 @@ const cmd: Command = {
|
|
|
139
144
|
console.error(` ${done}/${todo} (${((done / Math.max(1, todo)) * 100).toFixed(0)}%) ${(done / sec).toFixed(1)} ์ฅ/์ด`);
|
|
140
145
|
}, 5000);
|
|
141
146
|
|
|
147
|
+
let sfx: SfxMix | undefined;
|
|
148
|
+
let sfxCues = 0;
|
|
142
149
|
let segFiles: string[] = [];
|
|
143
150
|
let events: MotionEvent[] = [];
|
|
144
151
|
let segments: { rendered: string[]; reused: string[] } | undefined;
|
|
@@ -209,13 +216,24 @@ const cmd: Command = {
|
|
|
209
216
|
if (format !== "png") {
|
|
210
217
|
const list = join(tmp, "list.txt");
|
|
211
218
|
writeFileSync(list, segFiles.map((f) => `file '${f.replace(/'/g, "'\\''")}'`).join("\n") + "\n");
|
|
212
|
-
//
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
219
|
+
// ํจ๊ณผ์ โ ์ฐ๋ ๋์ ํ์ด์ง๊ฐ ๋จ๊ธด ์๋ฆฌ ์๋ฆฌ๋ฅผ ๋ฐ๋๋๋ก ๊ฑธ๋ฌ ๊น๋ค. ๋๋ฉด(--sfx offยทkf.json sfx: false) ์๋๋ ํจ๊ณผ์ ์ด์ ๊ณผ ๊ฐ์ ๊ธธ
|
|
220
|
+
const settings = opts["no-music"] ? null : sfxSettings(resolve(dir), sfxFlag);
|
|
221
|
+
if (settings) {
|
|
222
|
+
const bank = loadBank();
|
|
223
|
+
if (!bank.sets.includes(settings.set)) throw new Error(`ํจ๊ณผ์ ๊ฒฐ "${settings.set}" ์ด ์๋ค โ ์๋ ๊ฒฐ: ${bank.sets.join(" ยท ")}`);
|
|
224
|
+
const cues = cuesOf(events, settings.only && !settings.only.includes("drop") ? [] : projectDrops(resolve(dir)));
|
|
225
|
+
sfx = { hits: placeSfx(cues, settings, bank, { from: startF / fps, to: endF / fps }), settings, bank };
|
|
226
|
+
sfxCues = cues.filter((c) => c.t >= startF / fps && c.t < endF / fps).length;
|
|
227
|
+
}
|
|
228
|
+
// kf.json ์ audio(์๊ธฐ ๊ฐ)๊ฐ ์์ผ๋ฉด ๋ด๋ ์ด์
ยท๊ณก์ ์์ ์๋ฆฌ๋ฅผ ์น๋๋ค(๋ํนยท๋ ํ์ด๋ยทLUFS) โ ์์ผ๋ฉด ๊ณก๋ง. ํจ๊ณผ์์ ๊น๋ฉด audio ๊ฐ ์์ด๋ ์๋๋ค
|
|
229
|
+
const found = opts["no-music"] ? null : mixSettings(resolve(dir));
|
|
230
|
+
const mix = found ?? (sfx?.hits.length ? { audio: SFX_AUDIO, voice: undefined } : null);
|
|
231
|
+
const mixed = mix && (mix.voice || music || sfx?.hits.length)
|
|
232
|
+
? await mixAudio({ voice: mix.voice, music, musicFrom: songFrom }, { audio: mix.audio, from: startF / fps, dur: frames / fps, total: meta.duration, out: join(tmp, "mix.wav"), sfx })
|
|
216
233
|
: undefined;
|
|
217
234
|
await concat({ list, out, format, music: mixed ?? music, from: mixed ? 0 : songFrom + startF / fps, dur: frames / fps });
|
|
218
|
-
|
|
235
|
+
const layers = [mix?.voice ? "๋ด๋ ์ด์
" : "", music ? "๊ณก" : "", sfx?.hits.length ? `ํจ๊ณผ์ ${sfx.hits.length}(${sfx.settings.set})` : ""].filter(Boolean);
|
|
236
|
+
if (mixed) console.error(`์๋ฆฌ: ${layers.join(" + ")} โ ${mix!.audio.lufs} LUFS`);
|
|
219
237
|
}
|
|
220
238
|
const sec = (Date.now() - started) / 1000;
|
|
221
239
|
const report = {
|
|
@@ -230,6 +248,15 @@ const cmd: Command = {
|
|
|
230
248
|
motionBlur: blur,
|
|
231
249
|
captions: captions ?? null,
|
|
232
250
|
music: music ?? null,
|
|
251
|
+
sfx: sfx
|
|
252
|
+
? {
|
|
253
|
+
...sfx.settings,
|
|
254
|
+
cues: sfxCues,
|
|
255
|
+
placed: sfx.hits.length,
|
|
256
|
+
...(sfx.measured ? { lufs: { bed: sfx.measured.bed, sfx: sfx.measured.sfx, lift: sfx.measured.lift } } : {}),
|
|
257
|
+
hits: sfx.measured?.hits ?? sfx.hits,
|
|
258
|
+
}
|
|
259
|
+
: null,
|
|
233
260
|
seconds: Math.round(sec * 10) / 10,
|
|
234
261
|
...(segments ? { segments } : {}),
|
|
235
262
|
markers: s.info.markers,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { type Command, parseFlags } from "../command.ts";
|
|
3
|
+
import { commandFor, current, isNewer, noticeLine, refresh, upgrade } from "../update.ts";
|
|
4
|
+
|
|
5
|
+
async function confirm(q: string): Promise<boolean> {
|
|
6
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
7
|
+
try {
|
|
8
|
+
return /^(|y|yes|ใ
|์|๋ค)$/i.test((await rl.question(q)).trim());
|
|
9
|
+
} catch {
|
|
10
|
+
return false;
|
|
11
|
+
} finally {
|
|
12
|
+
rl.close();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const cmd: Command = {
|
|
17
|
+
summary: "์ ํ ํ์ธยท์ฌ๋ฆฌ๊ธฐ โ ์ง๊ธ ๋ ์ง์คํธ๋ฆฌ๋ฅผ ๋ณด๊ณ ์ ํ์ด๋ฉด ๊น ๋ฐฉ์(npmยทpnpmยทbunยทyarn)๋๋ก ์ฌ๋ฆฐ๋ค",
|
|
18
|
+
usage: `kf update ์ง๊ธ ํ์ธํ๊ณ ์ ํ์ด๋ฉด ์ฌ๋ฆฐ๋ค(ํฐ๋ฏธ๋์ด๋ฉด ํ ๋ฒ ๋ฌป๋๋ค)
|
|
19
|
+
kf update --check ์ฌ๋ฆฌ์ง ์๊ณ ๋ณด๊ธฐ๋ง
|
|
20
|
+
kf update --json {current, latest, update, command} ๋ฅผ ํ์ค ์ถ๋ ฅ์ โ ์ฌ๋ฆฌ์ง ์๋๋ค
|
|
21
|
+
kf update --yes ๋ฌป์ง ์๊ณ ์ฌ๋ฆฐ๋ค(์์ด์ ํธ์ฉ โ ํ์ค ์ค๋ฅ์ ใ[kasaframe] ์ ํ โฆใ ์ค์ด ๋ณด์ด๋ฉด)
|
|
22
|
+
๋ ์ง์คํธ๋ฆฌ๋ npm ์ค์ (npm_config_registryยท~/.npmrc)์ ๋ฐ๋ฅธ๋ค. kf ๋ ๋ช ์๊ฐ์ ํ ๋ฒ ๋ค์์ ํ์ธํด ๋๊ณ ,
|
|
23
|
+
์ ํ์ ์๋ฉด ํฐ๋ฏธ๋์์ ๋ช
๋ น ์ ์ ๋ฌป๊ณ ์๋๋ฉด ํ์ค ์ค๋ฅ์ ํ ์ค ์ฐ๋๋ค. ๋๊ธฐ: KF_NO_UPDATE_CHECK=1 ยท CI
|
|
24
|
+
์ข
๋ฃ ์ฝ๋: 0 ์ต์ ์ด๊ฑฐ๋ ์ฌ๋ฆผ ยท 1 ํ์ธยท์ค์น ์คํจ ยท 2 ์ฌ๋ฆฌ์ง ์์(๋ฌป๊ธฐ ๊ฑฐ์ ยท--yes ์์ด ํฐ๋ฏธ๋ ๋ฐยท๋ ํฌ ์ฒดํฌ์์)`,
|
|
25
|
+
async run(argv) {
|
|
26
|
+
const { opts } = parseFlags(argv);
|
|
27
|
+
let latest: string;
|
|
28
|
+
try {
|
|
29
|
+
latest = await refresh();
|
|
30
|
+
} catch (e) {
|
|
31
|
+
const error = (e as Error).message;
|
|
32
|
+
if (opts.json) console.log(JSON.stringify({ current, latest: null, update: false, command: null, error }));
|
|
33
|
+
else console.error(`kf update: ์ ํ์ ํ์ธํ์ง ๋ชปํ๋ค โ ${error}`);
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
const update = isNewer(latest, current);
|
|
37
|
+
const command = update ? commandFor(latest) : null;
|
|
38
|
+
if (opts.json) {
|
|
39
|
+
console.log(JSON.stringify({ current, latest, update, command: command?.join(" ") ?? null }));
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
if (!update) {
|
|
43
|
+
console.log(`kasaframe ${current} โ ์ต์ ์ด๋ค${latest === current ? "" : `(๋ ์ง์คํธ๋ฆฌ ์ต์ ${latest})`}`);
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
if (!command) {
|
|
47
|
+
console.log(`${noticeLine(latest)}\n๋ ํฌ ์ฒดํฌ์์์์ ๋๊ณ ์๋ค โ ์ค์น๋ณธ์ด ์๋๋ผ ์ฌ๋ฆฌ์ง ์๋๋ค(git pull)`);
|
|
48
|
+
return opts.check ? 0 : 2;
|
|
49
|
+
}
|
|
50
|
+
if (opts.check) {
|
|
51
|
+
console.log(`${noticeLine(latest)}\n์ฌ๋ฆฌ๋ ๋ช
๋ น: ${command.join(" ")}`);
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
if (!opts.yes) {
|
|
55
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
56
|
+
console.error(`${noticeLine(latest)}\nํฐ๋ฏธ๋์ด ์๋๋ผ ๋ฌป์ง ๋ชปํ๋ค โ ๋ฌป์ง ์๊ณ ์ฌ๋ฆฌ๋ ค๋ฉด kf update --yes`);
|
|
57
|
+
return 2;
|
|
58
|
+
}
|
|
59
|
+
if (!(await confirm(`kasaframe ${current} โ ${latest} ๋ก ์ฌ๋ฆด๊น(${command.join(" ")})? [Y/n] `))) return 2;
|
|
60
|
+
}
|
|
61
|
+
if (!upgrade(command, latest)) return 1;
|
|
62
|
+
console.log(`kasaframe ${latest} ๋ก ์ฌ๋ ธ๋ค`);
|
|
63
|
+
return 0;
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
export default cmd;
|