voicci 1.0.7 → 1.0.9
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/package.json +1 -1
- package/scripts/postinstall.js +81 -39
- package/.github/workflows/publish.yml +0 -69
- package/.github/workflows/test.yml +0 -33
- package/install.sh +0 -198
- package/lib/book-finder-old.js.backup +0 -263
- package/lib/queue-sqlite.js.backup +0 -242
- package/lib/text-cleaner-v2.js +0 -612
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "voicci",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "AI-Powered Audiobook Generator for Claude Code, OpenCode & AI Code Editors. Convert books and PDFs to audiobooks using natural language.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cli/index.js",
|
package/scripts/postinstall.js
CHANGED
|
@@ -9,10 +9,33 @@ import { execFileSync } from 'child_process';
|
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = path.dirname(__filename);
|
|
11
11
|
|
|
12
|
-
//
|
|
13
|
-
const
|
|
12
|
+
// Two skill files: simple and detailed
|
|
13
|
+
const SKILL_NAME_SIMPLE = 'voicci.md';
|
|
14
|
+
const SKILL_NAME_DETAILED = 'voicci-audiobook.md';
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const SKILL_CONTENT_SIMPLE = `---
|
|
17
|
+
description: "Voicci - AI audiobook generator"
|
|
18
|
+
argument-hint: "COMMAND_OR_FILE"
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Voicci - AI Audiobook Generator
|
|
22
|
+
|
|
23
|
+
Convert books, PDFs, and documents to audiobooks using AI text-to-speech.
|
|
24
|
+
|
|
25
|
+
## Quick Examples
|
|
26
|
+
- \`/voicci "Lord of the Rings"\` - Search and convert book
|
|
27
|
+
- \`/voicci mybook.pdf\` - Convert local file
|
|
28
|
+
- \`/voicci -s\` - Check job status
|
|
29
|
+
- \`/voicci -l\` - List audiobooks
|
|
30
|
+
- \`/voicci --help\` - Show all options
|
|
31
|
+
|
|
32
|
+
\`\`\`!
|
|
33
|
+
#!/bin/bash
|
|
34
|
+
voicci $ARGUMENTS
|
|
35
|
+
\`\`\`
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const SKILL_CONTENT_DETAILED = `---
|
|
16
39
|
description: "Voicci - AI audiobook generator CLI"
|
|
17
40
|
argument-hint: "COMMAND_OR_FILE"
|
|
18
41
|
---
|
|
@@ -113,14 +136,16 @@ const EDITORS = {
|
|
|
113
136
|
return false;
|
|
114
137
|
}
|
|
115
138
|
},
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
// Install to both skills/ and commands/ so slash commands appear in autocomplete
|
|
140
|
+
skillsDirs: () => [
|
|
141
|
+
path.join(os.homedir(), '.claude', 'commands'),
|
|
142
|
+
path.join(os.homedir(), '.claude', 'skills')
|
|
143
|
+
]
|
|
118
144
|
},
|
|
119
145
|
'OpenCode': {
|
|
120
146
|
name: 'OpenCode',
|
|
121
147
|
detect: () => {
|
|
122
148
|
const homeDir = os.homedir();
|
|
123
|
-
// Check for opencode command or config directory
|
|
124
149
|
if (fs.existsSync(path.join(homeDir, '.opencode'))) return true;
|
|
125
150
|
try {
|
|
126
151
|
execFileSync('which', ['opencode'], { stdio: 'ignore' });
|
|
@@ -129,14 +154,12 @@ const EDITORS = {
|
|
|
129
154
|
return false;
|
|
130
155
|
}
|
|
131
156
|
},
|
|
132
|
-
|
|
133
|
-
skillName: SKILL_NAME
|
|
157
|
+
skillsDirs: () => [path.join(os.homedir(), '.opencode', 'skills')]
|
|
134
158
|
},
|
|
135
159
|
'Cursor': {
|
|
136
160
|
name: 'Cursor',
|
|
137
161
|
detect: () => {
|
|
138
162
|
const homeDir = os.homedir();
|
|
139
|
-
// Check for cursor command or config directory
|
|
140
163
|
if (fs.existsSync(path.join(homeDir, '.cursor'))) return true;
|
|
141
164
|
if (fs.existsSync(path.join(homeDir, 'Library', 'Application Support', 'Cursor'))) return true;
|
|
142
165
|
try {
|
|
@@ -146,26 +169,23 @@ const EDITORS = {
|
|
|
146
169
|
return false;
|
|
147
170
|
}
|
|
148
171
|
},
|
|
149
|
-
|
|
172
|
+
skillsDirs: () => {
|
|
150
173
|
const homeDir = os.homedir();
|
|
151
|
-
// Try common locations
|
|
152
174
|
const locations = [
|
|
153
175
|
path.join(homeDir, '.cursor', 'skills'),
|
|
154
176
|
path.join(homeDir, 'Library', 'Application Support', 'Cursor', 'skills')
|
|
155
177
|
];
|
|
156
178
|
for (const loc of locations) {
|
|
157
179
|
const parent = path.dirname(loc);
|
|
158
|
-
if (fs.existsSync(parent)) return loc;
|
|
180
|
+
if (fs.existsSync(parent)) return [loc];
|
|
159
181
|
}
|
|
160
|
-
return locations[0];
|
|
161
|
-
}
|
|
162
|
-
skillName: SKILL_NAME
|
|
182
|
+
return [locations[0]];
|
|
183
|
+
}
|
|
163
184
|
},
|
|
164
185
|
'Windsurf': {
|
|
165
186
|
name: 'Windsurf',
|
|
166
187
|
detect: () => {
|
|
167
188
|
const homeDir = os.homedir();
|
|
168
|
-
// Check for windsurf command or config directory
|
|
169
189
|
if (fs.existsSync(path.join(homeDir, '.windsurf'))) return true;
|
|
170
190
|
try {
|
|
171
191
|
execFileSync('which', ['windsurf'], { stdio: 'ignore' });
|
|
@@ -174,11 +194,26 @@ const EDITORS = {
|
|
|
174
194
|
return false;
|
|
175
195
|
}
|
|
176
196
|
},
|
|
177
|
-
|
|
178
|
-
skillName: SKILL_NAME
|
|
197
|
+
skillsDirs: () => [path.join(os.homedir(), '.windsurf', 'skills')]
|
|
179
198
|
}
|
|
180
199
|
};
|
|
181
200
|
|
|
201
|
+
function installSkillFile(skillsDir, skillName, content) {
|
|
202
|
+
const skillFile = path.join(skillsDir, skillName);
|
|
203
|
+
|
|
204
|
+
// Check if already installed
|
|
205
|
+
if (fs.existsSync(skillFile)) {
|
|
206
|
+
const existingContent = fs.readFileSync(skillFile, 'utf8');
|
|
207
|
+
if (existingContent.includes('voicci $ARGUMENTS')) {
|
|
208
|
+
return 'exists';
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Write the skill file
|
|
213
|
+
fs.writeFileSync(skillFile, content, 'utf8');
|
|
214
|
+
return 'new';
|
|
215
|
+
}
|
|
216
|
+
|
|
182
217
|
function detectAndInstall() {
|
|
183
218
|
const homeDir = os.homedir();
|
|
184
219
|
const installedEditors = [];
|
|
@@ -192,29 +227,35 @@ function detectAndInstall() {
|
|
|
192
227
|
if (editor.detect()) {
|
|
193
228
|
console.log(`✓ Found ${editor.name}`);
|
|
194
229
|
|
|
195
|
-
const
|
|
196
|
-
const skillFile = path.join(skillsDir, editor.skillName);
|
|
230
|
+
const dirs = editor.skillsDirs();
|
|
197
231
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
232
|
+
let anyNew = false;
|
|
233
|
+
let allExist = true;
|
|
234
|
+
|
|
235
|
+
for (const skillsDir of dirs) {
|
|
236
|
+
// Create directory if it doesn't exist
|
|
237
|
+
if (!fs.existsSync(skillsDir)) {
|
|
238
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Install both skills
|
|
242
|
+
const simpleStatus = installSkillFile(skillsDir, SKILL_NAME_SIMPLE, SKILL_CONTENT_SIMPLE);
|
|
243
|
+
const detailedStatus = installSkillFile(skillsDir, SKILL_NAME_DETAILED, SKILL_CONTENT_DETAILED);
|
|
202
244
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
console.log(` ↳ Skill already installed at: ${skillFile}`);
|
|
209
|
-
installedEditors.push({ name: editor.name, path: skillFile, status: 'exists' });
|
|
210
|
-
continue;
|
|
245
|
+
if (simpleStatus === 'new' || detailedStatus === 'new') {
|
|
246
|
+
anyNew = true;
|
|
247
|
+
allExist = false;
|
|
248
|
+
if (simpleStatus === 'new') console.log(` ↳ Installed: ${path.join(skillsDir, SKILL_NAME_SIMPLE)}`);
|
|
249
|
+
if (detailedStatus === 'new') console.log(` ↳ Installed: ${path.join(skillsDir, SKILL_NAME_DETAILED)}`);
|
|
211
250
|
}
|
|
212
251
|
}
|
|
213
252
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
253
|
+
if (!anyNew) {
|
|
254
|
+
console.log(` ↳ Skills already installed`);
|
|
255
|
+
installedEditors.push({ name: editor.name, status: 'exists' });
|
|
256
|
+
} else {
|
|
257
|
+
installedEditors.push({ name: editor.name, status: 'new' });
|
|
258
|
+
}
|
|
218
259
|
}
|
|
219
260
|
} catch (error) {
|
|
220
261
|
failedEditors.push({ name: editor.name, error: error.message });
|
|
@@ -227,7 +268,7 @@ function detectAndInstall() {
|
|
|
227
268
|
if (installedEditors.length > 0) {
|
|
228
269
|
console.log('\n✅ Voicci CLI installed successfully!');
|
|
229
270
|
console.log('\n📦 Command-line tool: voicci');
|
|
230
|
-
console.log('🔧 Skill
|
|
271
|
+
console.log('🔧 Skill commands: /voicci OR /voicci-audiobook');
|
|
231
272
|
console.log('\n📍 Installed in:');
|
|
232
273
|
installedEditors.forEach(editor => {
|
|
233
274
|
const status = editor.status === 'new' ? '(new)' : '(already installed)';
|
|
@@ -236,8 +277,9 @@ function detectAndInstall() {
|
|
|
236
277
|
|
|
237
278
|
console.log('\n💡 Usage:');
|
|
238
279
|
console.log(' 1. Restart your AI code editor');
|
|
239
|
-
console.log(' 2. Use: /voicci
|
|
240
|
-
console.log(' 3. Or
|
|
280
|
+
console.log(' 2. Use: /voicci "search query" (simple)');
|
|
281
|
+
console.log(' 3. Or: /voicci-audiobook "search query" (detailed docs)');
|
|
282
|
+
console.log(' 4. Or CLI: voicci "your search query"');
|
|
241
283
|
} else {
|
|
242
284
|
console.log('\n⚠️ No supported AI code editors detected');
|
|
243
285
|
console.log('\nSupported editors: Claude Code, OpenCode, Cursor, Windsurf');
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
test:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: Checkout code
|
|
14
|
-
uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- name: Setup Node.js
|
|
17
|
-
uses: actions/setup-node@v4
|
|
18
|
-
with:
|
|
19
|
-
node-version: '18'
|
|
20
|
-
|
|
21
|
-
- name: Install dependencies
|
|
22
|
-
run: npm ci
|
|
23
|
-
|
|
24
|
-
- name: Run tests
|
|
25
|
-
run: npm test
|
|
26
|
-
|
|
27
|
-
publish:
|
|
28
|
-
needs: test
|
|
29
|
-
runs-on: ubuntu-latest
|
|
30
|
-
|
|
31
|
-
steps:
|
|
32
|
-
- name: Checkout code
|
|
33
|
-
uses: actions/checkout@v4
|
|
34
|
-
|
|
35
|
-
- name: Setup Node.js
|
|
36
|
-
uses: actions/setup-node@v4
|
|
37
|
-
with:
|
|
38
|
-
node-version: '18'
|
|
39
|
-
registry-url: 'https://registry.npmjs.org'
|
|
40
|
-
|
|
41
|
-
- name: Install dependencies
|
|
42
|
-
run: npm ci
|
|
43
|
-
|
|
44
|
-
- name: Publish to npm
|
|
45
|
-
run: npm publish
|
|
46
|
-
env:
|
|
47
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
48
|
-
|
|
49
|
-
- name: Create GitHub Release
|
|
50
|
-
uses: actions/create-release@v1
|
|
51
|
-
env:
|
|
52
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
53
|
-
with:
|
|
54
|
-
tag_name: ${{ github.ref }}
|
|
55
|
-
release_name: Release ${{ github.ref }}
|
|
56
|
-
body: |
|
|
57
|
-
## Installation
|
|
58
|
-
```bash
|
|
59
|
-
npm install -g voicci
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Or via install script:
|
|
63
|
-
```bash
|
|
64
|
-
curl -fsSL https://voicci.com/voicci-cli/install.sh | bash
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
See [CHANGELOG.md](https://github.com/voicci/voicci-cli/blob/main/CHANGELOG.md) for details.
|
|
68
|
-
draft: false
|
|
69
|
-
prerelease: false
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
name: Run Tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ main ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ main ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
|
|
13
|
-
strategy:
|
|
14
|
-
matrix:
|
|
15
|
-
node-version: [18.x, 20.x]
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- name: Checkout code
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: Setup Node.js ${{ matrix.node-version }}
|
|
22
|
-
uses: actions/setup-node@v4
|
|
23
|
-
with:
|
|
24
|
-
node-version: ${{ matrix.node-version }}
|
|
25
|
-
|
|
26
|
-
- name: Install dependencies
|
|
27
|
-
run: npm ci
|
|
28
|
-
|
|
29
|
-
- name: Run tests
|
|
30
|
-
run: npm test
|
|
31
|
-
|
|
32
|
-
- name: Check package can be packed
|
|
33
|
-
run: npm pack --dry-run
|
package/install.sh
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Voicci Installer
|
|
4
|
-
# Converts PDF/text files to high-quality audiobooks using XTTS v2 AI
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
# Colors for output
|
|
9
|
-
RED='\033[0;31m'
|
|
10
|
-
GREEN='\033[0;32m'
|
|
11
|
-
YELLOW='\033[1;33m'
|
|
12
|
-
BLUE='\033[0;34m'
|
|
13
|
-
NC='\033[0m' # No Color
|
|
14
|
-
|
|
15
|
-
echo -e "${BLUE}╔════════════════════════════════════════╗${NC}"
|
|
16
|
-
echo -e "${BLUE}║ Voicci Installer v1.0 ║${NC}"
|
|
17
|
-
echo -e "${BLUE}║ AI Audiobook Generator (XTTS v2) ║${NC}"
|
|
18
|
-
echo -e "${BLUE}╚════════════════════════════════════════╝${NC}"
|
|
19
|
-
echo ""
|
|
20
|
-
|
|
21
|
-
# Detect OS
|
|
22
|
-
OS="$(uname -s)"
|
|
23
|
-
case "${OS}" in
|
|
24
|
-
Linux*) OS_TYPE=Linux;;
|
|
25
|
-
Darwin*) OS_TYPE=Mac;;
|
|
26
|
-
*) OS_TYPE="UNKNOWN:${OS}"
|
|
27
|
-
esac
|
|
28
|
-
|
|
29
|
-
if [[ "$OS_TYPE" == "UNKNOWN"* ]]; then
|
|
30
|
-
echo -e "${RED}✗${NC} Unsupported operating system: ${OS}"
|
|
31
|
-
echo "Voicci currently supports macOS and Linux only."
|
|
32
|
-
exit 1
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
echo -e "${GREEN}✓${NC} Detected OS: ${OS_TYPE}"
|
|
36
|
-
|
|
37
|
-
# Check dependencies
|
|
38
|
-
echo ""
|
|
39
|
-
echo "Checking dependencies..."
|
|
40
|
-
|
|
41
|
-
# Check Node.js
|
|
42
|
-
if command -v node &> /dev/null; then
|
|
43
|
-
NODE_VERSION=$(node --version)
|
|
44
|
-
echo -e "${GREEN}✓${NC} Node.js $NODE_VERSION found"
|
|
45
|
-
else
|
|
46
|
-
echo -e "${RED}✗${NC} Node.js not found"
|
|
47
|
-
echo "Please install Node.js 18+ from https://nodejs.org/"
|
|
48
|
-
exit 1
|
|
49
|
-
fi
|
|
50
|
-
|
|
51
|
-
# Check npm
|
|
52
|
-
if command -v npm &> /dev/null; then
|
|
53
|
-
NPM_VERSION=$(npm --version)
|
|
54
|
-
echo -e "${GREEN}✓${NC} npm $NPM_VERSION found"
|
|
55
|
-
else
|
|
56
|
-
echo -e "${RED}✗${NC} npm not found"
|
|
57
|
-
exit 1
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
# Check Python
|
|
61
|
-
if command -v python3 &> /dev/null; then
|
|
62
|
-
PYTHON_VERSION=$(python3 --version 2>&1 | awk '{print $2}')
|
|
63
|
-
PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d. -f1)
|
|
64
|
-
PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d. -f2)
|
|
65
|
-
|
|
66
|
-
if [[ $PYTHON_MAJOR -ge 3 ]] && [[ $PYTHON_MINOR -ge 9 ]]; then
|
|
67
|
-
echo -e "${GREEN}✓${NC} Python $PYTHON_VERSION found"
|
|
68
|
-
else
|
|
69
|
-
echo -e "${RED}✗${NC} Python 3.9+ required (found $PYTHON_VERSION)"
|
|
70
|
-
exit 1
|
|
71
|
-
fi
|
|
72
|
-
else
|
|
73
|
-
echo -e "${RED}✗${NC} Python 3 not found"
|
|
74
|
-
echo "Please install Python 3.9+ from https://www.python.org/"
|
|
75
|
-
exit 1
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
# Check pip
|
|
79
|
-
if command -v pip3 &> /dev/null; then
|
|
80
|
-
echo -e "${GREEN}✓${NC} pip3 found"
|
|
81
|
-
else
|
|
82
|
-
echo -e "${RED}✗${NC} pip3 not found"
|
|
83
|
-
exit 1
|
|
84
|
-
fi
|
|
85
|
-
|
|
86
|
-
# Check pdftotext (optional but recommended)
|
|
87
|
-
if command -v pdftotext &> /dev/null; then
|
|
88
|
-
echo -e "${GREEN}✓${NC} pdftotext found"
|
|
89
|
-
else
|
|
90
|
-
echo -e "${YELLOW}⚠${NC} pdftotext not found (optional, for PDF support)"
|
|
91
|
-
echo "Install with: brew install poppler (Mac) or apt-get install poppler-utils (Linux)"
|
|
92
|
-
fi
|
|
93
|
-
|
|
94
|
-
# Determine installation directory
|
|
95
|
-
if [[ "$OS_TYPE" == "Mac" ]]; then
|
|
96
|
-
INSTALL_DIR="$HOME/Library/Application Support/voicci"
|
|
97
|
-
else
|
|
98
|
-
INSTALL_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voicci"
|
|
99
|
-
fi
|
|
100
|
-
|
|
101
|
-
echo ""
|
|
102
|
-
echo -e "Installation directory: ${BLUE}$INSTALL_DIR${NC}"
|
|
103
|
-
echo ""
|
|
104
|
-
|
|
105
|
-
# Ask for confirmation
|
|
106
|
-
read -p "Continue with installation? (y/n) " -n 1 -r
|
|
107
|
-
echo
|
|
108
|
-
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
109
|
-
echo "Installation cancelled."
|
|
110
|
-
exit 0
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
# Create installation directory
|
|
114
|
-
echo ""
|
|
115
|
-
echo "Creating directories..."
|
|
116
|
-
mkdir -p "$INSTALL_DIR"/{lib,cli,backend}
|
|
117
|
-
echo -e "${GREEN}✓${NC} Directories created"
|
|
118
|
-
|
|
119
|
-
# Download Voicci files (in production, this would download from GitHub/website)
|
|
120
|
-
echo ""
|
|
121
|
-
echo "Installing Voicci..."
|
|
122
|
-
|
|
123
|
-
# For now, we'll create the files directly
|
|
124
|
-
# In production, this would be: curl -fsSL https://voicci.com/voicci-cli/voicci.tar.gz | tar -xz -C "$INSTALL_DIR"
|
|
125
|
-
|
|
126
|
-
# Install Node.js dependencies
|
|
127
|
-
cd "$INSTALL_DIR"
|
|
128
|
-
echo ""
|
|
129
|
-
echo "Installing Node.js dependencies..."
|
|
130
|
-
|
|
131
|
-
cat > package.json <<'EOF'
|
|
132
|
-
{
|
|
133
|
-
"name": "voicci",
|
|
134
|
-
"version": "1.0.0",
|
|
135
|
-
"description": "AI Audiobook Generator using XTTS v2",
|
|
136
|
-
"type": "module",
|
|
137
|
-
"bin": {
|
|
138
|
-
"voicci": "./cli/index.js"
|
|
139
|
-
},
|
|
140
|
-
"dependencies": {
|
|
141
|
-
"commander": "^11.1.0",
|
|
142
|
-
"better-sqlite3": "^9.2.2",
|
|
143
|
-
"uuid": "^9.0.1",
|
|
144
|
-
"ink": "^4.4.1",
|
|
145
|
-
"react": "^18.2.0",
|
|
146
|
-
"chalk": "^5.3.0"
|
|
147
|
-
},
|
|
148
|
-
"engines": {
|
|
149
|
-
"node": ">=18.0.0"
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
EOF
|
|
153
|
-
|
|
154
|
-
npm install --silent --no-audit --no-fund 2>&1 | grep -v "npm WARN"
|
|
155
|
-
echo -e "${GREEN}✓${NC} Node.js dependencies installed"
|
|
156
|
-
|
|
157
|
-
# Install Python dependencies
|
|
158
|
-
echo ""
|
|
159
|
-
echo "Installing Python dependencies..."
|
|
160
|
-
echo "This may take several minutes (downloading XTTS v2 model ~450MB)..."
|
|
161
|
-
|
|
162
|
-
pip3 install --quiet --upgrade pip
|
|
163
|
-
pip3 install --quiet TTS torch torchaudio
|
|
164
|
-
|
|
165
|
-
echo -e "${GREEN}✓${NC} Python dependencies installed"
|
|
166
|
-
|
|
167
|
-
# Download XTTS v2 model
|
|
168
|
-
echo ""
|
|
169
|
-
echo "Downloading XTTS v2 model (this may take a few minutes)..."
|
|
170
|
-
python3 -c "from TTS.api import TTS; TTS('tts_models/multilingual/multi-dataset/xtts_v2')" &>/dev/null || true
|
|
171
|
-
echo -e "${GREEN}✓${NC} XTTS v2 model downloaded"
|
|
172
|
-
|
|
173
|
-
# Create symlink for global access
|
|
174
|
-
BIN_DIR="/usr/local/bin"
|
|
175
|
-
if [[ -w "$BIN_DIR" ]]; then
|
|
176
|
-
ln -sf "$INSTALL_DIR/cli/index.js" "$BIN_DIR/voicci"
|
|
177
|
-
echo -e "${GREEN}✓${NC} Global command 'voicci' installed"
|
|
178
|
-
else
|
|
179
|
-
echo -e "${YELLOW}⚠${NC} Could not create global command (insufficient permissions)"
|
|
180
|
-
echo "Add to your PATH manually: export PATH=\"$INSTALL_DIR/cli:\$PATH\""
|
|
181
|
-
fi
|
|
182
|
-
|
|
183
|
-
# Final message
|
|
184
|
-
echo ""
|
|
185
|
-
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
|
|
186
|
-
echo -e "${GREEN}║ Installation Complete! 🎉 ║${NC}"
|
|
187
|
-
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
|
|
188
|
-
echo ""
|
|
189
|
-
echo "Usage:"
|
|
190
|
-
echo -e " ${BLUE}voicci mybook.pdf${NC} - Convert PDF to audiobook"
|
|
191
|
-
echo -e " ${BLUE}voicci -s${NC} - Check all job statuses"
|
|
192
|
-
echo -e " ${BLUE}voicci -l${NC} - List completed audiobooks"
|
|
193
|
-
echo -e " ${BLUE}voicci -o <jobId>${NC} - Open audiobook folder"
|
|
194
|
-
echo ""
|
|
195
|
-
echo "Installation location: $INSTALL_DIR"
|
|
196
|
-
echo ""
|
|
197
|
-
echo "Get started: voicci --help"
|
|
198
|
-
echo ""
|