diff --git a/typescript-version/package-lock.json b/typescript-version/package-lock.json
index f628402..c37fb63 100644
--- a/typescript-version/package-lock.json
+++ b/typescript-version/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "twitch-vod-manager",
- "version": "3.7.8",
+ "version": "3.7.9",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "twitch-vod-manager",
- "version": "3.7.8",
+ "version": "3.7.9",
"license": "MIT",
"dependencies": {
"axios": "^1.6.0",
diff --git a/typescript-version/package.json b/typescript-version/package.json
index b5c4498..2fb00ae 100644
--- a/typescript-version/package.json
+++ b/typescript-version/package.json
@@ -1,6 +1,6 @@
{
"name": "twitch-vod-manager",
- "version": "3.7.8",
+ "version": "3.7.9",
"description": "Twitch VOD Manager - Download Twitch VODs easily",
"main": "dist/main.js",
"author": "xRangerDE",
diff --git a/typescript-version/src/index.html b/typescript-version/src/index.html
index 3d96f63..65fb60c 100644
--- a/typescript-version/src/index.html
+++ b/typescript-version/src/index.html
@@ -335,7 +335,7 @@
Updates
-
Version: v3.7.8
+
Version: v3.7.9
@@ -346,7 +346,7 @@
Nicht verbunden
- v3.7.8
+ v3.7.9
diff --git a/typescript-version/src/main.ts b/typescript-version/src/main.ts
index 433ada3..6936eaf 100644
--- a/typescript-version/src/main.ts
+++ b/typescript-version/src/main.ts
@@ -8,7 +8,7 @@ import { autoUpdater } from 'electron-updater';
// ==========================================
// CONFIG & CONSTANTS
// ==========================================
-const APP_VERSION = '3.7.8';
+const APP_VERSION = '3.7.9';
const UPDATE_CHECK_URL = 'http://24-music.de/version.json';
// Paths
@@ -172,6 +172,7 @@ let currentDownloadCancelled = false;
let downloadStartTime = 0;
let downloadedBytes = 0;
const userIdLoginCache = new Map();
+let streamlinkCommandCache: { command: string; prefixArgs: string[] } | null = null;
// ==========================================
// TOOL PATHS
@@ -201,6 +202,52 @@ function getStreamlinkPath(): string {
return 'streamlink';
}
+function canExecute(cmd: string): boolean {
+ try {
+ execSync(cmd, { stdio: 'ignore', windowsHide: true });
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+function getStreamlinkCommand(): { command: string; prefixArgs: string[] } {
+ if (streamlinkCommandCache) {
+ return streamlinkCommandCache;
+ }
+
+ const directPath = getStreamlinkPath();
+ if (directPath !== 'streamlink' || canExecute('streamlink --version')) {
+ streamlinkCommandCache = { command: directPath, prefixArgs: [] };
+ return streamlinkCommandCache;
+ }
+
+ if (process.platform === 'win32') {
+ if (canExecute('py -3 -m streamlink --version')) {
+ streamlinkCommandCache = { command: 'py', prefixArgs: ['-3', '-m', 'streamlink'] };
+ return streamlinkCommandCache;
+ }
+
+ if (canExecute('python -m streamlink --version')) {
+ streamlinkCommandCache = { command: 'python', prefixArgs: ['-m', 'streamlink'] };
+ return streamlinkCommandCache;
+ }
+ } else {
+ if (canExecute('python3 -m streamlink --version')) {
+ streamlinkCommandCache = { command: 'python3', prefixArgs: ['-m', 'streamlink'] };
+ return streamlinkCommandCache;
+ }
+
+ if (canExecute('python -m streamlink --version')) {
+ streamlinkCommandCache = { command: 'python', prefixArgs: ['-m', 'streamlink'] };
+ return streamlinkCommandCache;
+ }
+ }
+
+ streamlinkCommandCache = { command: directPath, prefixArgs: [] };
+ return streamlinkCommandCache;
+}
+
function getFFmpegPath(): string {
try {
if (process.platform === 'win32') {
@@ -777,8 +824,8 @@ function downloadVODPart(
totalParts: number
): Promise {
return new Promise((resolve) => {
- const streamlinkPath = getStreamlinkPath();
- const args = [url, 'best', '-o', filename, '--force'];
+ const streamlinkCmd = getStreamlinkCommand();
+ const args = [...streamlinkCmd.prefixArgs, url, 'best', '-o', filename, '--force'];
let lastErrorLine = '';
if (startTime) {
@@ -788,10 +835,10 @@ function downloadVODPart(
args.push('--hls-duration', endTime);
}
- console.log('Starting download:', streamlinkPath, args);
- appendDebugLog('download-part-start', { itemId, streamlinkPath, filename, args });
+ console.log('Starting download:', streamlinkCmd.command, args);
+ appendDebugLog('download-part-start', { itemId, command: streamlinkCmd.command, filename, args });
- const proc = spawn(streamlinkPath, args, { windowsHide: true });
+ const proc = spawn(streamlinkCmd.command, args, { windowsHide: true });
currentProcess = proc;
downloadStartTime = Date.now();
@@ -890,8 +937,12 @@ function downloadVODPart(
clearInterval(progressInterval);
console.error('Process error:', err);
currentProcess = null;
- appendDebugLog('download-part-process-error', { itemId, error: String(err) });
- resolve({ success: false, error: String(err) });
+ const rawError = String(err);
+ const errorMessage = rawError.includes('ENOENT')
+ ? 'Streamlink nicht gefunden. Installiere Streamlink oder Python+streamlink (py -3 -m pip install streamlink).'
+ : rawError;
+ appendDebugLog('download-part-process-error', { itemId, error: errorMessage, rawError });
+ resolve({ success: false, error: errorMessage });
});
});
}