mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
Merge pull request #2 from ZHANGTIANYAO1/claude/start-music-api-servers-bL8Wo
Ensure ffmpeg binary has execute permissions on startup
This commit is contained in:
2 files changed
+29
-2
No files matched your search
@@ -292,6 +292,13 @@ A:可以。在设置页面创建多个实例,分别连接不同的 TS 服务
|
|||||||
**Q:端口 3200 被占用?**
|
**Q:端口 3200 被占用?**
|
||||||
A:QQ 音乐 API 启动时自动监听 3200 端口。如果之前的进程还在运行,程序会自动复用。如需重启可手动结束 `node` 进程。
|
A:QQ 音乐 API 启动时自动监听 3200 端口。如果之前的进程还在运行,程序会自动复用。如需重启可手动结束 `node` 进程。
|
||||||
|
|
||||||
|
**Q:播放歌曲时报 FFmpeg EACCES 错误?**
|
||||||
|
A:`ffmpeg-static` 内置的 FFmpeg 二进制文件缺少执行权限。程序已自动尝试修复,如果仍然失败,请手动执行:
|
||||||
|
```bash
|
||||||
|
chmod +x node_modules/ffmpeg-static/ffmpeg
|
||||||
|
```
|
||||||
|
或者确保系统已安装 FFmpeg(`apt install ffmpeg` / `brew install ffmpeg`),程序会自动回退使用系统版本。
|
||||||
|
|
||||||
**Q:Docker 构建失败?**
|
**Q:Docker 构建失败?**
|
||||||
A:原生模块(opus、sqlite3)需要编译工具,Dockerfile 已包含。确保 Docker 有足够内存(建议 2GB+)。
|
A:原生模块(opus、sqlite3)需要编译工具,Dockerfile 已包含。确保 Docker 有足够内存(建议 2GB+)。
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -1,6 +1,7 @@
|
|||||||
import { spawn, type ChildProcess } from "node:child_process";
|
import { spawn, type ChildProcess } from "node:child_process";
|
||||||
import { EventEmitter } from "node:events";
|
import { EventEmitter } from "node:events";
|
||||||
import { createRequire } from "node:module";
|
import { createRequire } from "node:module";
|
||||||
|
import { accessSync, chmodSync, constants } from "node:fs";
|
||||||
import { createOpusEncoder, PCM_FRAME_BYTES, type Encoder } from "./encoder.js";
|
import { createOpusEncoder, PCM_FRAME_BYTES, type Encoder } from "./encoder.js";
|
||||||
import type { Logger } from "../logger.js";
|
import type { Logger } from "../logger.js";
|
||||||
|
|
||||||
@@ -8,10 +9,29 @@ import type { Logger } from "../logger.js";
|
|||||||
const require = createRequire(import.meta.url);
|
const require = createRequire(import.meta.url);
|
||||||
const ffmpegPath: string | null = require("ffmpeg-static");
|
const ffmpegPath: string | null = require("ffmpeg-static");
|
||||||
|
|
||||||
|
/** Ensure the given binary has execute permission. */
|
||||||
|
function isExecutable(binPath: string): boolean {
|
||||||
|
try {
|
||||||
|
accessSync(binPath, constants.X_OK);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
chmodSync(binPath, 0o755);
|
||||||
|
accessSync(binPath, constants.X_OK);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resolved once at module load — no repeated fs checks per play(). */
|
||||||
|
const resolvedFfmpeg: string =
|
||||||
|
ffmpegPath && isExecutable(ffmpegPath) ? ffmpegPath : "ffmpeg";
|
||||||
|
|
||||||
/** Resolve ffmpeg binary: prefer bundled ffmpeg-static, fall back to system PATH. */
|
/** Resolve ffmpeg binary: prefer bundled ffmpeg-static, fall back to system PATH. */
|
||||||
function getFfmpegCommand(): string {
|
function getFfmpegCommand(): string {
|
||||||
if (ffmpegPath) return ffmpegPath;
|
return resolvedFfmpeg;
|
||||||
return "ffmpeg"; // fallback to system-installed ffmpeg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlayerEvents {
|
export interface PlayerEvents {
|
||||||
|
|||||||
Reference in new issue
Block a user