diff --git a/apps/vhs/.gitignore b/apps/vhs/.gitignore new file mode 100644 index 0000000..f19b2f7 --- /dev/null +++ b/apps/vhs/.gitignore @@ -0,0 +1,2 @@ +bin/** +!bin/.gitkeep \ No newline at end of file diff --git a/apps/vhs/README.md b/apps/vhs/README.md new file mode 100644 index 0000000..d0a3db9 --- /dev/null +++ b/apps/vhs/README.md @@ -0,0 +1 @@ +# @robonen/vhs \ No newline at end of file diff --git a/apps/vhs/bin/.gitkeep b/apps/vhs/bin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/vhs/jsr.json b/apps/vhs/jsr.json new file mode 100644 index 0000000..d67b397 --- /dev/null +++ b/apps/vhs/jsr.json @@ -0,0 +1,5 @@ +{ + "name": "@robonen/vhs", + "version": "0.0.0", + "exports": "./src/index.ts" +} \ No newline at end of file diff --git a/apps/vhs/package.json b/apps/vhs/package.json new file mode 100644 index 0000000..90cf52c --- /dev/null +++ b/apps/vhs/package.json @@ -0,0 +1,26 @@ +{ + "name": "@robonen/vhs", + "private": true, + "version": "0.0.1", + "license": "UNLICENSED", + "description": "", + "keywords": [], + "author": "Robonen Andrew ", + "repository": { + "type": "git", + "url": "git+https://github.com/robonen/tools.git", + "directory": "./apps/vhs" + }, + "packageManager": "pnpm@9.11.0", + "engines": { + "bun": ">=1.1.27" + }, + "type": "module", + "scripts": { + "start": "bun run src/index.ts" + }, + "devDependencies": { + "@robonen/tsconfig": "workspace:*", + "@types/bun": "^1.1.10" + } +} diff --git a/apps/vhs/src/index.ts b/apps/vhs/src/index.ts new file mode 100644 index 0000000..db14658 --- /dev/null +++ b/apps/vhs/src/index.ts @@ -0,0 +1,36 @@ +import { version } from '../package.json'; +import { resolve } from 'path'; +import { $, Glob } from 'bun'; + +async function ffmpegMergeAndTranscodeAvi(files: Set) { + const ffmpeg = resolve('bin/ffmpeg'); + const output = resolve('output.mp4'); + const input = Array.from(files).toSorted((a, b) => a.localeCompare(b)).join('|'); + + const shell = $`${ffmpeg} -i "concat:${input}" -stats -c:v libx264 -crf 23 -preset veryfast -c:a aac ${output}`; + + for await (const line of shell.lines()) { + console.log(line); + } +} + +const path = Bun.argv[2]; + +if (!path) { + console.error('Please provide a path to a file or directory'); + process.exit(1); +} + +console.info(`Welcome to VHS v${version} 📼`); +console.info(`Scanning ${path}...`); + +const glob = new Glob(resolve(path)); +const files = new Set(); + +for await (const file of glob.scan({ followSymlinks: false })) { + files.add(file); +} + +console.info(`Found ${files.size} files`); + +console.info(await ffmpegMergeAndTranscodeAvi(files)); \ No newline at end of file diff --git a/apps/vhs/tsconfig.json b/apps/vhs/tsconfig.json new file mode 100644 index 0000000..d6d22e4 --- /dev/null +++ b/apps/vhs/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@robonen/tsconfig/tsconfig.json" +} \ No newline at end of file diff --git a/cli.ts b/cli.ts index 7954ae1..9654104 100644 --- a/cli.ts +++ b/cli.ts @@ -3,10 +3,10 @@ import { defineCommand, runMain } from 'citty'; import { resolve } from 'pathe'; import { splitByCase } from 'scule'; -const PACKAGE_MANAGER = 'pnpm@9.1.3'; -const NODE_VERSION = '>=20.13.1'; -const VITE_VERSION = '^5.2.11'; -const VITE_DTS_VERSION = '^3.9.1'; +const PACKAGE_MANAGER = 'pnpm@9.11.0'; +const NODE_VERSION = '>=20.17.0'; +const VITE_VERSION = '^5.4.8'; +const VITE_DTS_VERSION = '^4.2.2'; const PATHE_VERSION = '^1.1.2' const DEFAULT_DIR = 'packages'; diff --git a/packages/tsconfig/tsconfig.json b/packages/tsconfig/tsconfig.json index 49be4fe..0073d22 100644 --- a/packages/tsconfig/tsconfig.json +++ b/packages/tsconfig/tsconfig.json @@ -3,7 +3,7 @@ "display": "Base TypeScript Configuration", "compilerOptions": { /* Basic Options */ - "module": "Preserve", + "module": "ESNext", "noEmit": true, "lib": ["ESNext"], "moduleResolution": "Bundler",