@codearcade/subtitle-generator 1.0.1 → 1.0.3

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 (2) hide show
  1. package/init/index.js +86 -60
  2. package/package.json +1 -1
package/init/index.js CHANGED
@@ -47,27 +47,35 @@ const init = async () => {
47
47
 
48
48
  const file = fs.createWriteStream(dest);
49
49
 
50
- await res.body.pipeTo(
51
- new WritableStream({
52
- write(chunk) {
53
- downloaded += chunk.length;
54
- if (total) {
55
- const percent = ((downloaded / total) * 100).toFixed(2);
56
- process.stdout.write(`Downloading ${label}... ${percent}%\r`);
57
- } else {
58
- process.stdout.write(`Downloaded ${downloaded} bytes\r`);
59
- }
60
- file.write(chunk);
61
- },
62
- close() {
63
- file.end();
64
- console.log(`\n${label} download complete.`);
65
- },
66
- abort(err) {
67
- file.destroy(err);
68
- },
69
- }),
70
- );
50
+ // Wait for both the pipeTo AND the file stream to fully close
51
+ // so the file handle is released before we try to use the file.
52
+ await new Promise((resolve, reject) => {
53
+ file.on("close", resolve);
54
+ file.on("error", reject);
55
+
56
+ res.body.pipeTo(
57
+ new WritableStream({
58
+ write(chunk) {
59
+ downloaded += chunk.length;
60
+ if (total) {
61
+ const percent = ((downloaded / total) * 100).toFixed(2);
62
+ process.stdout.write(`Downloading ${label}... ${percent}%\r`);
63
+ } else {
64
+ process.stdout.write(`Downloaded ${downloaded} bytes\r`);
65
+ }
66
+ file.write(chunk);
67
+ },
68
+ close() {
69
+ file.end(); // triggers 'close' event on the file stream once flushed
70
+ console.log(`\n${label} download complete.`);
71
+ },
72
+ abort(err) {
73
+ file.destroy(err);
74
+ reject(err);
75
+ },
76
+ }),
77
+ ).catch(reject);
78
+ });
71
79
  }
72
80
 
73
81
  // 1. Download the AI Model
@@ -113,9 +121,6 @@ const init = async () => {
113
121
  );
114
122
  }
115
123
 
116
- // https://github.com/ggml-org/whisper.cpp/releases/download/v1.8.4/whisper-bin-Win32.zip
117
- // https://github.com/ggml-org/whisper.cpp/releases/v1.8.4/download/whisper-bin-Win32.zip
118
-
119
124
  const zipUrl = `https://github.com/ggml-org/whisper.cpp/releases/download/v1.8.4/${zipName}`;
120
125
  const zipPath = path.join(whisperDir, "whisper.zip");
121
126
 
@@ -123,48 +128,69 @@ const init = async () => {
123
128
 
124
129
  console.log("Extracting binary...");
125
130
 
126
- try {
127
- // Use PowerShell instead of tar to avoid the Windows bsdtar decompression bug
128
- execSync(
129
- `powershell -command "Expand-Archive -Force -LiteralPath '${zipPath}' -DestinationPath '${whisperDir}'"`,
130
- { stdio: "inherit" },
131
- );
132
-
133
- // 1. Move everything out of the "Release" folder
134
- const possibleReleaseDir = path.join(whisperDir, "Release");
135
-
136
- if (fs.existsSync(possibleReleaseDir)) {
137
- const files = fs.readdirSync(possibleReleaseDir);
138
-
139
- for (const file of files) {
140
- fs.renameSync(
141
- path.join(possibleReleaseDir, file),
142
- path.join(whisperDir, file),
131
+ let extractionSuccess = false;
132
+ let maxRetries = 5;
133
+ let retryDelay = 1000; // 1 second
134
+
135
+ // 1. The Retry Loop for safe extraction
136
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
137
+ try {
138
+ execSync(
139
+ `powershell -command "Expand-Archive -Force -LiteralPath '${zipPath}' -DestinationPath '${whisperDir}'"`,
140
+ { stdio: "inherit" },
141
+ );
142
+ extractionSuccess = true;
143
+ break; // It worked! Break out of the loop.
144
+ } catch (error) {
145
+ if (attempt === maxRetries) {
146
+ console.error(
147
+ `\nExtraction failed after ${maxRetries} attempts. File might be permanently locked or corrupted.`,
143
148
  );
149
+ throw error;
144
150
  }
145
- // Delete the now-empty Release folder
146
- fs.rmdirSync(possibleReleaseDir);
151
+ console.log(
152
+ `\nFile locked by Windows (likely Antivirus). Retrying in 1 second... (Attempt ${attempt} of ${maxRetries})`,
153
+ );
154
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
147
155
  }
156
+ }
148
157
 
149
- // 2. Rename extracted main.exe to match our wrapper expectations
150
- const extractedMain = path.join(whisperDir, "main.exe");
151
- if (fs.existsSync(extractedMain)) {
152
- fs.renameSync(extractedMain, binaryDest);
153
- } else {
154
- console.error("Warning: Could not find main.exe after extraction.");
155
- }
158
+ // 2. The Cleanup Phase (Only runs if extraction worked)
159
+ if (extractionSuccess) {
160
+ try {
161
+ // Move everything out of the "Release" folder
162
+ const possibleReleaseDir = path.join(whisperDir, "Release");
163
+
164
+ if (fs.existsSync(possibleReleaseDir)) {
165
+ const files = fs.readdirSync(possibleReleaseDir);
166
+
167
+ for (const file of files) {
168
+ fs.renameSync(
169
+ path.join(possibleReleaseDir, file),
170
+ path.join(whisperDir, file),
171
+ );
172
+ }
173
+ // Delete the now-empty Release folder
174
+ fs.rmdirSync(possibleReleaseDir);
175
+ }
156
176
 
157
- // 3. Clean up the zip file
158
- if (fs.existsSync(zipPath)) {
159
- fs.unlinkSync(zipPath);
160
- }
177
+ // Rename extracted main.exe to match our wrapper expectations
178
+ const extractedMain = path.join(whisperDir, "main.exe");
179
+ if (fs.existsSync(extractedMain)) {
180
+ fs.renameSync(extractedMain, binaryDest);
181
+ } else {
182
+ console.error("Warning: Could not find main.exe after extraction.");
183
+ }
161
184
 
162
- console.log(`Whisper binary setup complete for Windows (${arch}).`);
163
- } catch (error) {
164
- console.error(
165
- "Extraction failed. Please ensure PowerShell is available.",
166
- error.message,
167
- );
185
+ // Clean up the zip file
186
+ if (fs.existsSync(zipPath)) {
187
+ fs.unlinkSync(zipPath);
188
+ }
189
+
190
+ console.log(`Whisper binary setup complete for Windows (${arch}).`);
191
+ } catch (error) {
192
+ console.error("Error during binary cleanup/renaming:", error.message);
193
+ }
168
194
  }
169
195
  } else {
170
196
  console.log("Whisper binary already exists for Windows.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codearcade/subtitle-generator",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",