whatever, let's vibe coding
parent
b6065abbac
commit
445b8171a6
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
description: A description of your rule
|
||||||
|
---
|
||||||
|
|
||||||
|
Your rule content
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
import {spawn} from 'child_process';
|
import {spawn} from 'child_process';
|
||||||
import {readdir} from 'fs/promises';
|
import {readdir} from 'fs/promises';
|
||||||
import {createInterface} from 'node:readline';
|
import {createInterface} from 'node:readline';
|
||||||
|
import {runInBackground} from '../lib/ai-generated.ts';
|
||||||
|
import { extname } from 'node:path';
|
||||||
|
|
||||||
|
|
||||||
function formatTime(seconds: number): string {
|
function formatTime(seconds: number): string {
|
||||||
|
|
@ -39,9 +41,10 @@ async function getDuration(inputFile: string): Promise<number> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function compressVideo(inputFile: string, outputFile: string) {
|
async function compressVideo(inputFile: string, outputFile: string) {
|
||||||
const duration = await getDuration(inputFile);
|
const duration = await getDuration(inputFile);
|
||||||
return new Promise<void>(resolve => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const ffmpeg = spawn('ffmpeg', [
|
const ffmpeg = spawn('ffmpeg', [
|
||||||
'-hwaccel', 'cuda',
|
'-hwaccel', 'cuda',
|
||||||
|
|
@ -93,10 +96,11 @@ async function compressVideo(inputFile: string, outputFile: string) {
|
||||||
console.log(); // Новая строка в конце
|
console.log(); // Новая строка в конце
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
console.log(`✅ Completed: ${outputFile}`);
|
console.log(`✅ Completed: ${outputFile}`);
|
||||||
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
console.error(`❌ Failed with code ${code}`);
|
console.error(`❌ Failed with code ${code}`);
|
||||||
|
reject();
|
||||||
}
|
}
|
||||||
resolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ffmpeg.stderr.on('data', (data) => {
|
ffmpeg.stderr.on('data', (data) => {
|
||||||
|
|
@ -109,13 +113,17 @@ async function compressVideo(inputFile: string, outputFile: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const files = await readdir('.');
|
const files = (await readdir('.')).filter(name => {
|
||||||
const mp4Files = files.filter(file => file.match(/^VID_.*\.mp4$/));
|
return (!name.startsWith('HEVC') && ['mp4', 'mov'].includes(extname(name).toLowerCase().slice(1)))
|
||||||
const filesCount = mp4Files.length;
|
});
|
||||||
|
let filesCount = files.length;
|
||||||
|
|
||||||
for (let i = 0; i < filesCount; i++){
|
for (let i = 0; i < filesCount; i++){
|
||||||
const file = mp4Files[i];
|
const file = files[i];
|
||||||
const outputFile = `HEVC_${file.slice(4)}`;
|
|
||||||
|
// const outputFile = `HEVC_${file.slice(4)}`;
|
||||||
|
const outputFile = `HEVC_${file}`;
|
||||||
console.log(`\nProcessing: ${file} [${i + 1}/${filesCount}]`);
|
console.log(`\nProcessing: ${file} [${i + 1}/${filesCount}]`);
|
||||||
await compressVideo(file, outputFile);
|
await compressVideo(file, outputFile);
|
||||||
|
// runInBackground('identity', [file, outputFile])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { Ollama } from 'ollama';
|
||||||
|
import {getStdin} from '../lib/ai-generated.ts';
|
||||||
|
|
||||||
|
const ollama = new Ollama({ host: 'http://127.0.0.1:11434' });
|
||||||
|
const model = 'gemma3:12b';
|
||||||
|
// const model = 'codellama:13b';
|
||||||
|
// const model = 'aya:8b';
|
||||||
|
|
||||||
|
|
||||||
|
async function streamChat() {
|
||||||
|
let [,,message] = process.argv;
|
||||||
|
if (!message) return;
|
||||||
|
const file = getStdin();
|
||||||
|
const stream = await ollama.chat({
|
||||||
|
model,
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: `${message}\n${file}`},
|
||||||
|
],
|
||||||
|
stream: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const chunk of stream) {
|
||||||
|
process.stdout.write(chunk.message.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await streamChat();
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
function sortingAlgorithm(x: number[]): number[] {
|
||||||
|
for (let i = 0; i < x.length; i++) {
|
||||||
|
for (let j = 0; j < x.length - 1; j++) {
|
||||||
|
if (x[j] > x[j + 1]) {
|
||||||
|
[x[j], x[j + 1]] = [x[j + 1], x[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
5
bun.lock
5
bun.lock
|
|
@ -4,6 +4,7 @@
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.5.0",
|
"chalk": "^5.5.0",
|
||||||
|
"ollama": "^0.5.17",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^24.2.1",
|
"@types/node": "^24.2.1",
|
||||||
|
|
@ -15,6 +16,10 @@
|
||||||
|
|
||||||
"chalk": ["chalk@5.5.0", "", {}, "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg=="],
|
"chalk": ["chalk@5.5.0", "", {}, "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg=="],
|
||||||
|
|
||||||
|
"ollama": ["ollama@0.5.17", "", { "dependencies": { "whatwg-fetch": "^3.6.20" } }, "sha512-q5LmPtk6GLFouS+3aURIVl+qcAOPC4+Msmx7uBb3pd+fxI55WnGjmLZ0yijI/CYy79x0QPGx3BwC3u5zv9fBvQ=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
|
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
|
||||||
|
|
||||||
|
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { readdir, stat } from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
|
||||||
|
const videoExtensions = ['mp4', 'avi', 'mov', 'mkv', 'flv', 'wmv', 'mpeg', 'mpg'];
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const files = await readdir('.');
|
||||||
|
for (const file of files) {
|
||||||
|
const stats = await stat(file);
|
||||||
|
if (!stats.isFile()) continue;
|
||||||
|
|
||||||
|
const ext = path.extname(file).slice(1).toLowerCase();
|
||||||
|
if (videoExtensions.includes(ext) && !file.startsWith('HEVC_')) {
|
||||||
|
const newFileName = 'HEVC_' + file;
|
||||||
|
const command = `ffmpeg -i "${file}" -c:v hevc_nvenc -preset slow -crf 23 -c:a aac "${newFileName}"`;
|
||||||
|
|
||||||
|
exec(command, (err) => {
|
||||||
|
if (err) console.error(`Conversion failed for ${file}: ${err}`);
|
||||||
|
else console.log(`Converted ${file} → ${newFileName}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error processing files:', err);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import { readdir, stat } from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
const currentDir = './'; // Текущая директория
|
||||||
|
|
||||||
|
function isVideoFile(filePath: string): Promise<boolean> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
stat(filePath, (err, stats) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Ошибка при получении информации о файле ${filePath}:`, err);
|
||||||
|
resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ext = path.extname(filePath).toLowerCase();
|
||||||
|
const isVideo = ['.mp4', '.mov', '.avi', '.mkv'].includes(ext);
|
||||||
|
resolve(isVideo && stats.size > 0); // Убеждаемся, что файл не пустой
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function compressVideoWithFFmpeg(filePath: string): void {
|
||||||
|
const outputFilePath = `HEVC_${path.basename(filePath)}`;
|
||||||
|
exec(`ffmpeg -i ${filePath} -c:v hevc_nvenc ${outputFilePath}`, (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
console.error('Ошибка при сжатии видео:', error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (stderr) {
|
||||||
|
console.error('FFmpeg ошибка:', stderr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Сжата файл: ${filePath} в ${outputFilePath}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function walkThroughDirectory(dir: string): void {
|
||||||
|
readdir(dir, { withFileTypes: true }, (err, files) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Ошибка при чтении директории:', err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files.forEach((file) => {
|
||||||
|
const fullPath = path.join(dir, file.name);
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
walkThroughDirectory(fullPath); // Рекурсивно обходим поддиректории
|
||||||
|
} else {
|
||||||
|
isVideoFile(fullPath).then((isVideo) => {
|
||||||
|
if (isVideo) {
|
||||||
|
compressVideoWithFFmpeg(fullPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
walkThroughDirectory(currentDir);
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import {spawn} from 'child_process';
|
||||||
|
import {readFileSync} from 'node:fs';
|
||||||
|
|
||||||
|
export function runInBackground(command: string, args?: string[]) {
|
||||||
|
const proc = spawn(command, args ?? [], {detached: true, stdio: 'ignore'});
|
||||||
|
proc.unref();
|
||||||
|
return proc.pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getStdin = () => readFileSync(0, 'utf8');
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
"@types/node": "^24.2.1"
|
"@types/node": "^24.2.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.5.0"
|
"chalk": "^5.5.0",
|
||||||
|
"ollama": "^0.5.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue