koishi-plugin-chatsound 0.0.2 → 0.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.
package/lib/index.d.ts CHANGED
@@ -1,10 +1,20 @@
1
1
  import { Context, Schema } from 'koishi';
2
+ import SilkService from 'koishi-plugin-silk';
3
+ declare module 'koishi' {
4
+ interface Context {
5
+ silk: SilkService;
6
+ }
7
+ }
2
8
  export declare const name = "chatsound";
9
+ export declare const inject: {
10
+ required: string[];
11
+ };
3
12
  export interface Config {
4
13
  soundPath: string[];
5
14
  defaultPitch: number;
6
15
  minPitch: number;
7
16
  maxPitch: number;
17
+ audioType: "mp3" | "silk";
8
18
  }
9
19
  export declare const Config: Schema<Config>;
10
20
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -22,6 +22,7 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  Config: () => Config,
24
24
  apply: () => apply,
25
+ inject: () => inject,
25
26
  name: () => name
26
27
  });
27
28
  module.exports = __toCommonJS(src_exports);
@@ -32,11 +33,15 @@ var import_child_process = require("child_process");
32
33
  var import_util = require("util");
33
34
  var execAsync = (0, import_util.promisify)(import_child_process.exec);
34
35
  var name = "chatsound";
36
+ var inject = {
37
+ required: ["silk"]
38
+ };
35
39
  var Config = import_koishi.Schema.object({
36
40
  soundPath: import_koishi.Schema.array(import_koishi.Schema.string()).description("用于搜索的音频路径"),
37
41
  defaultPitch: import_koishi.Schema.number().default(100).description("默认的语音音调(百分比)"),
38
42
  minPitch: import_koishi.Schema.number().default(80).min(0).description("最小Pitch,不小于0"),
39
- maxPitch: import_koishi.Schema.number().default(200).description("最大Pitch")
43
+ maxPitch: import_koishi.Schema.number().default(200).description("最大Pitch"),
44
+ audioType: import_koishi.Schema.union(["mp3", "silk"]).default("mp3").description("最终发送的类型,QQ及微信选择SILK")
40
45
  });
41
46
  var AUDIO_EXTENSIONS = [".mp3", ".wav", ".ogg", ".flac", ".m4a", ".aac"];
42
47
  async function findAudioFile(trigger, soundPaths) {
@@ -59,11 +64,63 @@ async function findAudioFile(trigger, soundPaths) {
59
64
  return null;
60
65
  }
61
66
  __name(findAudioFile, "findAudioFile");
62
- async function applyPitch(inputPath, pitch) {
67
+ async function runFFmpeg(commandArgs) {
68
+ return new Promise((resolve, reject) => {
69
+ const ffmpeg = (0, import_child_process.spawn)("ffmpeg", commandArgs);
70
+ const chunks = [];
71
+ ffmpeg.stdout.on("data", (chunk) => chunks.push(chunk));
72
+ ffmpeg.stderr.on("data", (chunk) => {
73
+ });
74
+ ffmpeg.on("close", (code) => {
75
+ if (code === 0) {
76
+ resolve(Buffer.concat(chunks));
77
+ } else {
78
+ reject(new Error(`FFmpeg exited with code ${code}`));
79
+ }
80
+ });
81
+ ffmpeg.on("error", reject);
82
+ });
83
+ }
84
+ __name(runFFmpeg, "runFFmpeg");
85
+ async function applyPitch(inputPath, pitch, audioType) {
63
86
  const pitchFactor = pitch / 100;
64
- const command = `ffmpeg -i "${inputPath}" -filter:a "asetrate=44100*${pitchFactor},aresample=44100" -f mp3 -`;
65
- const { stdout } = await execAsync(command);
66
- return Buffer.from(stdout);
87
+ if (audioType === "mp3") {
88
+ const args = [
89
+ "-i",
90
+ inputPath,
91
+ "-vn",
92
+ "-sn",
93
+ "-dn",
94
+ "-filter:a",
95
+ `rubberband=pitch=${pitchFactor}`,
96
+ "-f",
97
+ "mp3",
98
+ "-y",
99
+ "pipe:1"
100
+ ];
101
+ const data = await runFFmpeg(args);
102
+ return { data, mimeType: "audio/mp3" };
103
+ } else {
104
+ const args = [
105
+ "-i",
106
+ inputPath,
107
+ "-vn",
108
+ "-sn",
109
+ "-dn",
110
+ "-filter:a",
111
+ `rubberband=pitch=${pitchFactor}`,
112
+ "-f",
113
+ "s16le",
114
+ "-ac",
115
+ "1",
116
+ "-ar",
117
+ "24000",
118
+ "-y",
119
+ "pipe:1"
120
+ ];
121
+ const data = await runFFmpeg(args);
122
+ return { data, mimeType: "audio/pcm" };
123
+ }
67
124
  }
68
125
  __name(applyPitch, "applyPitch");
69
126
  function apply(ctx, config) {
@@ -77,8 +134,13 @@ function apply(ctx, config) {
77
134
  return `没有这种音频`;
78
135
  }
79
136
  try {
80
- const audioBuffer = await applyPitch(audioPath, actualPitch);
81
- await session.send(import_koishi.h.audio(audioBuffer, "audio/mp3"));
137
+ const { data, mimeType } = await applyPitch(audioPath, actualPitch, config.audioType);
138
+ if (config.audioType === "silk") {
139
+ const silkResult = await ctx.silk.encode(data, 24e3);
140
+ await session.send(import_koishi.h.audio(silkResult.data, "audio/silk"));
141
+ } else {
142
+ await session.send(import_koishi.h.audio(data, mimeType));
143
+ }
82
144
  } catch (error) {
83
145
  ctx.logger.error("发送音频失败:", error);
84
146
  return "发送音频失败";
@@ -90,5 +152,6 @@ __name(apply, "apply");
90
152
  0 && (module.exports = {
91
153
  Config,
92
154
  apply,
155
+ inject,
93
156
  name
94
157
  });
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "contributors": [
5
5
  "Dr.Abc <me@drabc.net>"
6
6
  ],
7
- "version": "0.0.2",
7
+ "version": "0.0.3",
8
8
  "homepage": "https://github.com/DrAbcOfficial/koishi-plugin-chatsound",
9
9
  "repository": {
10
10
  "type": "git",
@@ -13,7 +13,8 @@
13
13
  "main": "lib/index.js",
14
14
  "typings": "lib/index.d.ts",
15
15
  "files": [
16
- "lib"
16
+ "lib",
17
+ "dist"
17
18
  ],
18
19
  "license": "MIT",
19
20
  "scripts": {},
@@ -31,6 +32,9 @@
31
32
  "en": "发送预定的噪音,可以变调,依赖ffmpeg",
32
33
  "zh": "发送预定的噪音,可以变调,依赖ffmpeg"
33
34
  },
35
+ "service":{
36
+ "required": ["silk"]
37
+ },
34
38
  "preview": true
35
39
  }
36
40
  }