mediacript 1.0.0 → 1.0.2

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 (55) hide show
  1. package/README.md +1 -1
  2. package/cli.mjs +13 -2
  3. package/dist/config/index.d.ts +22 -0
  4. package/dist/config/index.d.ts.map +1 -0
  5. package/dist/config/index.js +119 -0
  6. package/dist/config/index.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +226 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/transcript/groq.d.ts +9 -0
  12. package/dist/transcript/groq.d.ts.map +1 -0
  13. package/dist/transcript/groq.js +38 -0
  14. package/dist/transcript/groq.js.map +1 -0
  15. package/dist/transcript/index.d.ts +13 -0
  16. package/dist/transcript/index.d.ts.map +1 -0
  17. package/dist/transcript/index.js +50 -0
  18. package/dist/transcript/index.js.map +1 -0
  19. package/dist/transcript/openai.d.ts +8 -0
  20. package/dist/transcript/openai.d.ts.map +1 -0
  21. package/dist/transcript/openai.js +27 -0
  22. package/dist/transcript/openai.js.map +1 -0
  23. package/dist/types/index.d.ts +31 -0
  24. package/dist/types/index.d.ts.map +1 -0
  25. package/dist/types/index.js +2 -0
  26. package/dist/types/index.js.map +1 -0
  27. package/dist/utils/ffmpegCheck.d.ts +18 -0
  28. package/dist/utils/ffmpegCheck.d.ts.map +1 -0
  29. package/dist/utils/ffmpegCheck.js +74 -0
  30. package/dist/utils/ffmpegCheck.js.map +1 -0
  31. package/dist/utils/ffmpegOperations.d.ts +21 -0
  32. package/dist/utils/ffmpegOperations.d.ts.map +1 -0
  33. package/dist/utils/ffmpegOperations.js +117 -0
  34. package/dist/utils/ffmpegOperations.js.map +1 -0
  35. package/dist/utils/fileHelpers.d.ts +18 -0
  36. package/dist/utils/fileHelpers.d.ts.map +1 -0
  37. package/dist/utils/fileHelpers.js +59 -0
  38. package/dist/utils/fileHelpers.js.map +1 -0
  39. package/dist/workflow/state.d.ts +38 -0
  40. package/dist/workflow/state.d.ts.map +1 -0
  41. package/dist/workflow/state.js +119 -0
  42. package/dist/workflow/state.js.map +1 -0
  43. package/package.json +7 -1
  44. package/QUICK_START.md +0 -154
  45. package/src/config/index.ts +0 -136
  46. package/src/index.ts +0 -278
  47. package/src/transcript/groq.ts +0 -50
  48. package/src/transcript/index.ts +0 -60
  49. package/src/transcript/openai.ts +0 -34
  50. package/src/types/index.ts +0 -34
  51. package/src/utils/ffmpegCheck.ts +0 -78
  52. package/src/utils/ffmpegOperations.ts +0 -144
  53. package/src/utils/fileHelpers.ts +0 -60
  54. package/src/workflow/state.ts +0 -140
  55. package/tsconfig.json +0 -21
@@ -1,34 +0,0 @@
1
- export interface Config {
2
- openaiApiKey?: string
3
- groqApiKey?: string
4
- }
5
-
6
- export interface WorkflowStep {
7
- id: string
8
- name: string
9
- status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped'
10
- result?: any
11
- error?: string
12
- startTime?: number
13
- endTime?: number
14
- }
15
-
16
- export interface WorkflowState {
17
- steps: WorkflowStep[]
18
- currentStepIndex: number
19
- inputFile: string
20
- intermediateFiles: {
21
- convertedVideo?: string
22
- extractedAudio?: string
23
- transcriptionText?: string
24
- }
25
- }
26
-
27
- export type OperationType = 'convert-video' | 'extract-audio' | 'convert-audio' | 'transcribe'
28
-
29
- export interface Operation {
30
- type: OperationType
31
- name: string
32
- description: string
33
- requiresInput: 'video' | 'audio' | 'any'
34
- }
@@ -1,78 +0,0 @@
1
- import { execSync } from 'child_process'
2
-
3
- /**
4
- * Verifica se o ffmpeg está instalado e disponível no PATH
5
- */
6
- export function checkFfmpegInstalled(): { installed: boolean; version?: string; error?: string } {
7
- try {
8
- const output = execSync('ffmpeg -version', {
9
- encoding: 'utf-8',
10
- stdio: ['pipe', 'pipe', 'pipe']
11
- })
12
-
13
- // Extrai a versão da primeira linha
14
- const versionMatch = output.match(/ffmpeg version ([^\s]+)/)
15
- const version = versionMatch ? versionMatch[1] : 'unknown'
16
-
17
- return {
18
- installed: true,
19
- version
20
- }
21
- } catch (error: any) {
22
- return {
23
- installed: false,
24
- error: error.message
25
- }
26
- }
27
- }
28
-
29
- /**
30
- * Exibe instruções de instalação do ffmpeg baseado no sistema operacional
31
- */
32
- export function showFfmpegInstallInstructions(): void {
33
- const platform = process.platform
34
-
35
- console.log('\n⚠️ FFmpeg não está instalado ou não está disponível no PATH\n')
36
- console.log('📦 Instruções de instalação:\n')
37
-
38
- if (platform === 'win32') {
39
- console.log('Windows:')
40
- console.log(' 1. Usando Chocolatey:')
41
- console.log(' choco install ffmpeg')
42
- console.log('\n 2. Usando Scoop:')
43
- console.log(' scoop install ffmpeg')
44
- console.log('\n 3. Download manual:')
45
- console.log(' - Baixe de: https://ffmpeg.org/download.html')
46
- console.log(' - Extraia e adicione ao PATH do sistema')
47
- } else if (platform === 'darwin') {
48
- console.log('macOS:')
49
- console.log(' Usando Homebrew:')
50
- console.log(' brew install ffmpeg')
51
- } else {
52
- console.log('Linux:')
53
- console.log(' Ubuntu/Debian:')
54
- console.log(' sudo apt update && sudo apt install ffmpeg')
55
- console.log('\n Fedora:')
56
- console.log(' sudo dnf install ffmpeg')
57
- console.log('\n Arch Linux:')
58
- console.log(' sudo pacman -S ffmpeg')
59
- }
60
-
61
- console.log('\n💡 Após a instalação, reinicie o terminal e tente novamente.\n')
62
- }
63
-
64
- /**
65
- * Verifica e informa sobre a instalação do ffmpeg
66
- * Retorna true se instalado, false caso contrário
67
- */
68
- export function verifyFfmpeg(): boolean {
69
- const result = checkFfmpegInstalled()
70
-
71
- if (result.installed) {
72
- console.log(`✓ FFmpeg está instalado (versão: ${result.version})`)
73
- return true
74
- } else {
75
- showFfmpegInstallInstructions()
76
- return false
77
- }
78
- }
@@ -1,144 +0,0 @@
1
- import { spawn } from 'child_process'
2
- import path from 'path'
3
- import fs from 'fs'
4
-
5
- /**
6
- * Gera um caminho único para o arquivo de saída
7
- */
8
- export function uniqueOutputPath(dir: string, baseName: string, extWithDot: string): string {
9
- let candidate = path.join(dir, `${baseName}${extWithDot}`)
10
- if (!fs.existsSync(candidate)) return candidate
11
-
12
- for (let i = 1; i < 10_000; i++) {
13
- candidate = path.join(dir, `${baseName}_${i}${extWithDot}`)
14
- if (!fs.existsSync(candidate)) return candidate
15
- }
16
-
17
- throw new Error('Não foi possível gerar um nome de saída único.')
18
- }
19
-
20
- /**
21
- * Executa um comando ffmpeg
22
- */
23
- export function runFfmpegCommand(args: string[]): Promise<string> {
24
- return new Promise((resolve, reject) => {
25
- const ffmpeg = spawn('ffmpeg', args, {
26
- stdio: ['ignore', 'pipe', 'pipe']
27
- })
28
-
29
- let stdout = ''
30
- let stderr = ''
31
-
32
- ffmpeg.stdout.on('data', (data) => {
33
- stdout += data.toString()
34
- })
35
-
36
- ffmpeg.stderr.on('data', (data) => {
37
- stderr += data.toString()
38
- // FFmpeg envia progresso para stderr
39
- const lines = stderr.split('\n')
40
- const lastLine = lines[lines.length - 2] || ''
41
-
42
- // Exibe progresso se tiver informação de tempo
43
- if (lastLine.includes('time=')) {
44
- process.stdout.write(`\r${lastLine.trim()}`)
45
- }
46
- })
47
-
48
- ffmpeg.on('close', (code) => {
49
- process.stdout.write('\r')
50
- if (code === 0) {
51
- resolve(stdout)
52
- } else {
53
- reject(new Error(`FFmpeg falhou com código ${code}\n${stderr}`))
54
- }
55
- })
56
-
57
- ffmpeg.on('error', (err) => {
58
- reject(err)
59
- })
60
- })
61
- }
62
-
63
- /**
64
- * Converte vídeo para formato performático (H.264/AAC)
65
- */
66
- export async function convertVideo(
67
- inputPath: string,
68
- outputDir?: string
69
- ): Promise<string> {
70
- const dir = outputDir || path.dirname(inputPath)
71
- const baseName = path.basename(inputPath, path.extname(inputPath))
72
- const outputPath = uniqueOutputPath(dir, `${baseName}_converted`, '.mp4')
73
-
74
- console.log(`\n🎬 Convertendo vídeo para formato performático...`)
75
-
76
- const args = [
77
- '-i', inputPath,
78
- '-c:v', 'libx264',
79
- '-preset', 'medium',
80
- '-crf', '23',
81
- '-c:a', 'aac',
82
- '-b:a', '128k',
83
- '-movflags', '+faststart',
84
- '-y',
85
- outputPath
86
- ]
87
-
88
- await runFfmpegCommand(args)
89
- console.log(`\n✓ Vídeo convertido: ${path.basename(outputPath)}`)
90
- return outputPath
91
- }
92
-
93
- /**
94
- * Extrai áudio de um vídeo
95
- */
96
- export async function extractAudio(
97
- inputPath: string,
98
- outputDir?: string
99
- ): Promise<string> {
100
- const dir = outputDir || path.dirname(inputPath)
101
- const baseName = path.basename(inputPath, path.extname(inputPath))
102
- const outputPath = uniqueOutputPath(dir, `${baseName}_audio`, '.mp3')
103
-
104
- console.log(`\n🎵 Extraindo áudio do vídeo...`)
105
-
106
- const args = [
107
- '-i', inputPath,
108
- '-vn',
109
- '-acodec', 'libmp3lame',
110
- '-b:a', '192k',
111
- '-y',
112
- outputPath
113
- ]
114
-
115
- await runFfmpegCommand(args)
116
- console.log(`\n✓ Áudio extraído: ${path.basename(outputPath)}`)
117
- return outputPath
118
- }
119
-
120
- /**
121
- * Converte áudio para formato performático
122
- */
123
- export async function convertAudio(
124
- inputPath: string,
125
- outputDir?: string
126
- ): Promise<string> {
127
- const dir = outputDir || path.dirname(inputPath)
128
- const baseName = path.basename(inputPath, path.extname(inputPath))
129
- const outputPath = uniqueOutputPath(dir, `${baseName}_converted`, '.mp3')
130
-
131
- console.log(`\n🎵 Convertendo áudio para MP3...`)
132
-
133
- const args = [
134
- '-i', inputPath,
135
- '-acodec', 'libmp3lame',
136
- '-b:a', '192k',
137
- '-y',
138
- outputPath
139
- ]
140
-
141
- await runFfmpegCommand(args)
142
- console.log(`\n✓ Áudio convertido: ${path.basename(outputPath)}`)
143
- return outputPath
144
- }
@@ -1,60 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
-
4
- const AUDIO_EXTS = new Set(['.ogg', '.wav', '.mp3', '.m4a', '.aac', '.flac'])
5
- const VIDEO_EXTS = new Set(['.mp4', '.mov', '.mkv', '.webm', '.avi'])
6
-
7
- export type FileType = 'audio' | 'video' | 'unknown'
8
-
9
- /**
10
- * Detecta o tipo de arquivo pela extensão
11
- */
12
- export function detectFileType(filePath: string): FileType {
13
- const ext = path.extname(filePath).toLowerCase()
14
-
15
- if (AUDIO_EXTS.has(ext)) return 'audio'
16
- if (VIDEO_EXTS.has(ext)) return 'video'
17
- return 'unknown'
18
- }
19
-
20
- /**
21
- * Lista arquivos de áudio/vídeo no diretório
22
- */
23
- export function listMediaFiles(dir: string): Array<{ name: string; fullPath: string; type: FileType }> {
24
- try {
25
- return fs
26
- .readdirSync(dir)
27
- .filter((name) => {
28
- const fullPath = path.join(dir, name)
29
- try {
30
- return fs.statSync(fullPath).isFile()
31
- } catch {
32
- return false
33
- }
34
- })
35
- .map((name) => {
36
- const fullPath = path.join(dir, name)
37
- return {
38
- name,
39
- fullPath,
40
- type: detectFileType(name)
41
- }
42
- })
43
- .filter((f) => f.type !== 'unknown')
44
- .sort((a, b) => a.name.localeCompare(b.name))
45
- } catch (error) {
46
- console.error('Erro ao listar arquivos:', error)
47
- return []
48
- }
49
- }
50
-
51
- /**
52
- * Verifica se um arquivo existe
53
- */
54
- export function fileExists(filePath: string): boolean {
55
- try {
56
- return fs.existsSync(filePath) && fs.statSync(filePath).isFile()
57
- } catch {
58
- return false
59
- }
60
- }
@@ -1,140 +0,0 @@
1
- import fs from 'fs'
2
- import path from 'path'
3
- import { WorkflowState, WorkflowStep } from '../types/index.js'
4
-
5
- /**
6
- * Cria um novo workflow state
7
- */
8
- export function createWorkflowState(inputFile: string, stepNames: string[]): WorkflowState {
9
- return {
10
- steps: stepNames.map((name, index) => ({
11
- id: `step-${index}`,
12
- name,
13
- status: 'pending'
14
- })),
15
- currentStepIndex: 0,
16
- inputFile,
17
- intermediateFiles: {}
18
- }
19
- }
20
-
21
- /**
22
- * Atualiza o status de um step
23
- */
24
- export function updateStepStatus(
25
- state: WorkflowState,
26
- stepIndex: number,
27
- status: WorkflowStep['status'],
28
- result?: any,
29
- error?: string
30
- ): void {
31
- if (stepIndex >= 0 && stepIndex < state.steps.length) {
32
- const step = state.steps[stepIndex]
33
- step.status = status
34
-
35
- if (status === 'running') {
36
- step.startTime = Date.now()
37
- } else if (status === 'completed' || status === 'failed') {
38
- step.endTime = Date.now()
39
- }
40
-
41
- if (result !== undefined) {
42
- step.result = result
43
- }
44
-
45
- if (error) {
46
- step.error = error
47
- }
48
- }
49
- }
50
-
51
- /**
52
- * Obtém o step atual
53
- */
54
- export function getCurrentStep(state: WorkflowState): WorkflowStep | null {
55
- if (state.currentStepIndex < state.steps.length) {
56
- return state.steps[state.currentStepIndex]
57
- }
58
- return null
59
- }
60
-
61
- /**
62
- * Avança para o próximo step
63
- */
64
- export function nextStep(state: WorkflowState): boolean {
65
- if (state.currentStepIndex < state.steps.length - 1) {
66
- state.currentStepIndex++
67
- return true
68
- }
69
- return false
70
- }
71
-
72
- /**
73
- * Verifica se o workflow está completo
74
- */
75
- export function isWorkflowComplete(state: WorkflowState): boolean {
76
- return state.steps.every(step =>
77
- step.status === 'completed' || step.status === 'skipped'
78
- )
79
- }
80
-
81
- /**
82
- * Verifica se houve algum erro no workflow
83
- */
84
- export function hasWorkflowErrors(state: WorkflowState): boolean {
85
- return state.steps.some(step => step.status === 'failed')
86
- }
87
-
88
- /**
89
- * Exibe o progresso do workflow
90
- */
91
- export function printWorkflowProgress(state: WorkflowState): void {
92
- console.log('\n📊 Progresso do Workflow:')
93
- console.log('━'.repeat(50))
94
-
95
- state.steps.forEach((step, index) => {
96
- let icon = '⏳'
97
- if (step.status === 'completed') icon = '✓'
98
- else if (step.status === 'failed') icon = '✗'
99
- else if (step.status === 'running') icon = '⚡'
100
- else if (step.status === 'skipped') icon = '⊘'
101
-
102
- const duration = step.startTime && step.endTime
103
- ? ` (${((step.endTime - step.startTime) / 1000).toFixed(1)}s)`
104
- : ''
105
-
106
- console.log(`${icon} ${index + 1}. ${step.name}${duration}`)
107
-
108
- if (step.error) {
109
- console.log(` └─ Erro: ${step.error}`)
110
- }
111
- })
112
-
113
- console.log('━'.repeat(50))
114
- }
115
-
116
- /**
117
- * Salva o estado do workflow em arquivo
118
- */
119
- export function saveWorkflowState(state: WorkflowState, outputDir: string): void {
120
- const stateFile = path.join(outputDir, '.workflow-state.json')
121
- fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), 'utf-8')
122
- }
123
-
124
- /**
125
- * Carrega o estado do workflow de arquivo
126
- */
127
- export function loadWorkflowState(outputDir: string): WorkflowState | null {
128
- const stateFile = path.join(outputDir, '.workflow-state.json')
129
-
130
- try {
131
- if (fs.existsSync(stateFile)) {
132
- const data = fs.readFileSync(stateFile, 'utf-8')
133
- return JSON.parse(data)
134
- }
135
- } catch (error) {
136
- console.warn('Erro ao carregar estado do workflow:', error)
137
- }
138
-
139
- return null
140
- }
package/tsconfig.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ES2020",
5
- "moduleResolution": "node",
6
- "esModuleInterop": true,
7
- "skipLibCheck": true,
8
- "strict": true,
9
- "outDir": "./dist",
10
- "rootDir": "./src",
11
- "declaration": true,
12
- "declarationMap": true,
13
- "sourceMap": true
14
- },
15
- "include": ["src/**/*"],
16
- "exclude": ["node_modules", "dist"],
17
- "ts-node": {
18
- "esm": true,
19
- "experimentalSpecifierResolution": "node"
20
- }
21
- }