@kajidog/voicevox-client 0.4.1 → 0.5.0
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/LICENSE +14 -14
- package/dist/api.d.ts +36 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +76 -0
- package/dist/api.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -0
- package/dist/client.js.map +1 -1
- package/dist/effect/config.d.ts +43 -0
- package/dist/effect/config.d.ts.map +1 -0
- package/dist/effect/config.js +45 -0
- package/dist/effect/config.js.map +1 -0
- package/dist/effect/context.d.ts +33 -0
- package/dist/effect/context.d.ts.map +1 -0
- package/dist/effect/context.js +10 -0
- package/dist/effect/context.js.map +1 -0
- package/dist/effect/errors.d.ts +130 -0
- package/dist/effect/errors.d.ts.map +1 -0
- package/dist/effect/errors.js +121 -0
- package/dist/effect/errors.js.map +1 -0
- package/dist/effect/index.d.ts +34 -0
- package/dist/effect/index.d.ts.map +1 -0
- package/dist/effect/index.js +67 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/effect/queue-manager.d.ts +34 -0
- package/dist/effect/queue-manager.d.ts.map +1 -0
- package/dist/effect/queue-manager.js +59 -0
- package/dist/effect/queue-manager.js.map +1 -0
- package/dist/effect/services/api-service.d.ts +58 -0
- package/dist/effect/services/api-service.d.ts.map +1 -0
- package/dist/effect/services/api-service.js +90 -0
- package/dist/effect/services/api-service.js.map +1 -0
- package/dist/effect/services/audio-generator-service.d.ts +78 -0
- package/dist/effect/services/audio-generator-service.d.ts.map +1 -0
- package/dist/effect/services/audio-generator-service.js +187 -0
- package/dist/effect/services/audio-generator-service.js.map +1 -0
- package/dist/effect/services/audio-player-service.d.ts +101 -0
- package/dist/effect/services/audio-player-service.d.ts.map +1 -0
- package/dist/effect/services/audio-player-service.js +297 -0
- package/dist/effect/services/audio-player-service.js.map +1 -0
- package/dist/effect/services/event-manager-service.d.ts +96 -0
- package/dist/effect/services/event-manager-service.d.ts.map +1 -0
- package/dist/effect/services/event-manager-service.js +208 -0
- package/dist/effect/services/event-manager-service.js.map +1 -0
- package/dist/effect/services/file-manager-service.d.ts +91 -0
- package/dist/effect/services/file-manager-service.d.ts.map +1 -0
- package/dist/effect/services/file-manager-service.js +215 -0
- package/dist/effect/services/file-manager-service.js.map +1 -0
- package/dist/effect/utils.d.ts +118 -0
- package/dist/effect/utils.d.ts.map +1 -0
- package/dist/effect/utils.js +186 -0
- package/dist/effect/utils.js.map +1 -0
- package/dist/error.js.map +1 -1
- package/dist/player.d.ts +110 -0
- package/dist/player.d.ts.map +1 -0
- package/dist/player.js +183 -0
- package/dist/player.js.map +1 -0
- package/dist/queue/audio-player.d.ts +44 -0
- package/dist/queue/audio-player.d.ts.map +1 -0
- package/dist/queue/audio-player.js +344 -0
- package/dist/queue/audio-player.js.map +1 -0
- package/dist/queue/file-manager.js +9 -9
- package/dist/queue/manager.d.ts +134 -0
- package/dist/queue/manager.d.ts.map +1 -0
- package/dist/queue/manager.js +564 -0
- package/dist/queue/manager.js.map +1 -0
- package/dist/queue/queue-service.d.ts.map +1 -1
- package/dist/queue/queue-service.js +16 -4
- package/dist/queue/queue-service.js.map +1 -1
- package/dist/shared-queue-manager.d.ts +119 -0
- package/dist/shared-queue-manager.d.ts.map +1 -0
- package/dist/shared-queue-manager.js +487 -0
- package/dist/shared-queue-manager.js.map +1 -0
- package/dist/state/types.js.map +1 -1
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Effect-based AudioGenerator service implementation
|
|
4
|
+
* Provides structured error handling and resource management for audio generation
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.generateAudioWithPreprocessing = exports.batchGenerateAudio = exports.EffectAudioGeneratorServiceScoped = exports.EffectAudioGeneratorServiceLive = exports.makeEffectAudioGeneratorService = exports.EffectAudioGeneratorServiceImpl = exports.EffectAudioGeneratorContext = void 0;
|
|
8
|
+
const effect_1 = require("effect");
|
|
9
|
+
const audio_generator_1 = require("../../queue/audio-generator");
|
|
10
|
+
const context_1 = require("../context");
|
|
11
|
+
const errors_1 = require("../errors");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
exports.EffectAudioGeneratorContext = effect_1.Context.GenericTag('@voicevox/EffectAudioGenerator');
|
|
14
|
+
/**
|
|
15
|
+
* Effect-based implementation of AudioGenerator service
|
|
16
|
+
*/
|
|
17
|
+
class EffectAudioGeneratorServiceImpl {
|
|
18
|
+
constructor(audioGenerator) {
|
|
19
|
+
this.audioGenerator = audioGenerator;
|
|
20
|
+
/**
|
|
21
|
+
* Traditional generateQuery method (Promise-based)
|
|
22
|
+
*/
|
|
23
|
+
this.generateQuery = (text, speaker) => this.audioGenerator.generateQuery(text, speaker);
|
|
24
|
+
/**
|
|
25
|
+
* Traditional generateAudioFromQuery method (Promise-based)
|
|
26
|
+
*/
|
|
27
|
+
this.generateAudioFromQuery = (item, statusCallback) => this.audioGenerator.generateAudioFromQuery(item, statusCallback);
|
|
28
|
+
/**
|
|
29
|
+
* Traditional generateAudio method (Promise-based)
|
|
30
|
+
*/
|
|
31
|
+
this.generateAudio = (item, statusCallback) => this.audioGenerator.generateAudio(item, statusCallback);
|
|
32
|
+
/**
|
|
33
|
+
* Generate audio query with Effect-based error handling
|
|
34
|
+
*/
|
|
35
|
+
this.generateQueryEffect = (text, speaker) => (0, utils_1.logTimed)(`generateQueryEffect-speaker-${speaker}`, (0, errors_1.retryWithBackoff)((0, errors_1.safeAsync)(() => this.audioGenerator.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Failed to generate audio query in audio generator', text, speaker, error)), 3, // max retries
|
|
36
|
+
1000 // base delay 1s
|
|
37
|
+
));
|
|
38
|
+
/**
|
|
39
|
+
* Generate audio from text with Effect-based workflow
|
|
40
|
+
*/
|
|
41
|
+
this.generateAudioEffect = (item, updateStatus) => {
|
|
42
|
+
const self = this;
|
|
43
|
+
return (0, utils_1.logTimed)(`generateAudioEffect-${item.id}`, effect_1.Effect.gen(function* () {
|
|
44
|
+
// Check if item is in correct status
|
|
45
|
+
if (item.status !== 'pending') {
|
|
46
|
+
return item;
|
|
47
|
+
}
|
|
48
|
+
// Update status to generating
|
|
49
|
+
yield* updateStatus(item, 'generating');
|
|
50
|
+
// Generate query
|
|
51
|
+
const query = yield* self.generateQueryEffect(item.text, item.speaker);
|
|
52
|
+
// Get services from context
|
|
53
|
+
const apiService = yield* context_1.VoicevoxApiContext;
|
|
54
|
+
const fileService = yield* context_1.EffectFileManagerContext;
|
|
55
|
+
// Synthesize audio
|
|
56
|
+
const audioData = yield* (0, errors_1.safeAsync)(() => apiService.getApi().synthesize(query, item.speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize audio in audio generator', item.speaker, error));
|
|
57
|
+
// Save to temporary file
|
|
58
|
+
const tempFile = yield* fileService.saveTempAudioFile(audioData);
|
|
59
|
+
// Update item with generated data
|
|
60
|
+
const updatedItem = {
|
|
61
|
+
...item,
|
|
62
|
+
query,
|
|
63
|
+
tempFile,
|
|
64
|
+
status: 'ready',
|
|
65
|
+
};
|
|
66
|
+
// Update status to ready
|
|
67
|
+
yield* updateStatus(updatedItem, 'ready');
|
|
68
|
+
return updatedItem;
|
|
69
|
+
}));
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Generate audio from existing query with Effect-based workflow
|
|
73
|
+
*/
|
|
74
|
+
this.generateAudioFromQueryEffect = (item, updateStatus) => {
|
|
75
|
+
return (0, utils_1.logTimed)(`generateAudioFromQueryEffect-${item.id}`, effect_1.Effect.gen(function* () {
|
|
76
|
+
// Check if item is in correct status and has query
|
|
77
|
+
if (item.status !== 'pending' || !item.query) {
|
|
78
|
+
return item;
|
|
79
|
+
}
|
|
80
|
+
// Update status to generating
|
|
81
|
+
yield* updateStatus(item, 'generating');
|
|
82
|
+
// Get services from context
|
|
83
|
+
const apiService = yield* context_1.VoicevoxApiContext;
|
|
84
|
+
const fileService = yield* context_1.EffectFileManagerContext;
|
|
85
|
+
// Synthesize audio from existing query
|
|
86
|
+
const audioData = yield* (0, errors_1.safeAsync)(() => apiService.getApi().synthesize(item.query, item.speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize audio from query in audio generator', item.speaker, error));
|
|
87
|
+
// Save to temporary file
|
|
88
|
+
const tempFile = yield* fileService.saveTempAudioFile(audioData);
|
|
89
|
+
// Update item with generated data
|
|
90
|
+
const updatedItem = {
|
|
91
|
+
...item,
|
|
92
|
+
tempFile,
|
|
93
|
+
status: 'ready',
|
|
94
|
+
};
|
|
95
|
+
// Update status to ready
|
|
96
|
+
yield* updateStatus(updatedItem, 'ready');
|
|
97
|
+
return updatedItem;
|
|
98
|
+
}));
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Health check to verify audio generation capabilities
|
|
102
|
+
*/
|
|
103
|
+
this.healthCheck = () => {
|
|
104
|
+
const self = this;
|
|
105
|
+
return (0, utils_1.logTimed)('audioGeneratorHealthCheck', effect_1.Effect.gen(function* () {
|
|
106
|
+
// Try to generate a simple query as health check
|
|
107
|
+
const result = yield* self.generateQueryEffect('テスト', 1).pipe(effect_1.Effect.map(() => true), effect_1.Effect.catchAll(() => effect_1.Effect.succeed(false)));
|
|
108
|
+
return result;
|
|
109
|
+
}));
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.EffectAudioGeneratorServiceImpl = EffectAudioGeneratorServiceImpl;
|
|
114
|
+
/**
|
|
115
|
+
* Create AudioGenerator service instance
|
|
116
|
+
*/
|
|
117
|
+
const makeEffectAudioGeneratorService = () => effect_1.Effect.gen(function* () {
|
|
118
|
+
const apiService = yield* context_1.VoicevoxApiContext;
|
|
119
|
+
const fileManager = yield* context_1.EffectFileManagerContext;
|
|
120
|
+
// Get the underlying VoicevoxApi instance and create a dummy AudioFileManager for the AudioGenerator
|
|
121
|
+
const api = apiService.getApi();
|
|
122
|
+
// We need to create a bridge AudioFileManager that uses our Effect-based file service
|
|
123
|
+
const bridgeFileManager = {
|
|
124
|
+
saveTempAudioFile: (audioData) => effect_1.Effect.runPromise(fileManager.saveTempAudioFile(audioData)),
|
|
125
|
+
deleteTempFile: (filePath) => effect_1.Effect.runPromise(fileManager.deleteTempFile(filePath)),
|
|
126
|
+
releaseAllBlobUrls: () => effect_1.Effect.runPromise(fileManager.releaseAllBlobUrls()),
|
|
127
|
+
createTempFilePath: () => effect_1.Effect.runPromise(fileManager.createTempFilePath()),
|
|
128
|
+
createBlobUrl: (blob) => effect_1.Effect.runPromise(fileManager.createBlobUrl(blob)),
|
|
129
|
+
releaseBlobUrl: (url) => effect_1.Effect.runPromise(fileManager.releaseBlobUrl(url)),
|
|
130
|
+
};
|
|
131
|
+
const audioGenerator = new audio_generator_1.AudioGenerator(api, bridgeFileManager);
|
|
132
|
+
return new EffectAudioGeneratorServiceImpl(audioGenerator);
|
|
133
|
+
});
|
|
134
|
+
exports.makeEffectAudioGeneratorService = makeEffectAudioGeneratorService;
|
|
135
|
+
/**
|
|
136
|
+
* Layer providing Effect AudioGenerator service
|
|
137
|
+
*/
|
|
138
|
+
exports.EffectAudioGeneratorServiceLive = effect_1.Layer.effect(exports.EffectAudioGeneratorContext, (0, exports.makeEffectAudioGeneratorService)());
|
|
139
|
+
/**
|
|
140
|
+
* Scoped layer that automatically manages resources
|
|
141
|
+
*/
|
|
142
|
+
exports.EffectAudioGeneratorServiceScoped = effect_1.Layer.scoped(exports.EffectAudioGeneratorContext, effect_1.Effect.gen(function* () {
|
|
143
|
+
const service = yield* (0, exports.makeEffectAudioGeneratorService)();
|
|
144
|
+
// AudioGenerator doesn't need explicit cleanup but we can add monitoring
|
|
145
|
+
yield* effect_1.Effect.addFinalizer(() => effect_1.Effect.log('AudioGenerator service cleaned up'));
|
|
146
|
+
return service;
|
|
147
|
+
}));
|
|
148
|
+
/**
|
|
149
|
+
* Helper functions for audio generation workflows
|
|
150
|
+
*/
|
|
151
|
+
/**
|
|
152
|
+
* Batch generate audio from multiple text inputs
|
|
153
|
+
*/
|
|
154
|
+
const batchGenerateAudio = (texts, speaker, concurrency = 3) => {
|
|
155
|
+
const apiService = context_1.VoicevoxApiContext;
|
|
156
|
+
return effect_1.Effect.gen(function* () {
|
|
157
|
+
const service = yield* apiService;
|
|
158
|
+
const api = service.getApi();
|
|
159
|
+
// Generate all audio in parallel with limited concurrency
|
|
160
|
+
const audioDataArray = yield* effect_1.Effect.all(texts.map((text) => effect_1.Effect.gen(function* () {
|
|
161
|
+
const query = yield* (0, errors_1.safeAsync)(() => api.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Batch query generation failed', text, speaker, error));
|
|
162
|
+
const audioData = yield* (0, errors_1.safeAsync)(() => api.synthesize(query, speaker), (error) => (0, errors_1.makeSynthesisError)('Batch synthesis failed', speaker, error));
|
|
163
|
+
return audioData;
|
|
164
|
+
})), { concurrency });
|
|
165
|
+
return audioDataArray;
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
exports.batchGenerateAudio = batchGenerateAudio;
|
|
169
|
+
/**
|
|
170
|
+
* Generate audio with custom preprocessing
|
|
171
|
+
*/
|
|
172
|
+
const generateAudioWithPreprocessing = (text, speaker, preprocessor) => {
|
|
173
|
+
const apiService = context_1.VoicevoxApiContext;
|
|
174
|
+
return effect_1.Effect.gen(function* () {
|
|
175
|
+
const service = yield* apiService;
|
|
176
|
+
const api = service.getApi();
|
|
177
|
+
// Generate base query
|
|
178
|
+
const baseQuery = yield* (0, errors_1.safeAsync)(() => api.generateQuery(text, speaker), (error) => (0, errors_1.makeQueryGenerationError)('Failed to generate base query', text, speaker, error));
|
|
179
|
+
// Apply preprocessing
|
|
180
|
+
const processedQuery = preprocessor(baseQuery);
|
|
181
|
+
// Synthesize with processed query
|
|
182
|
+
const audioData = yield* (0, errors_1.safeAsync)(() => api.synthesize(processedQuery, speaker), (error) => (0, errors_1.makeSynthesisError)('Failed to synthesize processed audio', speaker, error));
|
|
183
|
+
return audioData;
|
|
184
|
+
});
|
|
185
|
+
};
|
|
186
|
+
exports.generateAudioWithPreprocessing = generateAudioWithPreprocessing;
|
|
187
|
+
//# sourceMappingURL=audio-generator-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-generator-service.js","sourceRoot":"","sources":["../../../src/effect/services/audio-generator-service.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mCAA+C;AAC/C,iEAA4D;AAG5D,wCAQmB;AACnB,sCASkB;AAClB,oCAAmC;AAsBtB,QAAA,2BAA2B,GAAG,gBAAO,CAAC,UAAU,CAC3D,gCAAgC,CACjC,CAAA;AAED;;GAEG;AACH,MAAa,+BAA+B;IAC1C,YAA6B,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;QAE3D;;WAEG;QACH,kBAAa,GAAG,CAAC,IAAY,EAAE,OAAe,EAAgB,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEjH;;WAEG;QACH,2BAAsB,GAAG,CAAC,IAAS,EAAE,cAAmD,EAAiB,EAAE,CACzG,IAAI,CAAC,cAAc,CAAC,sBAAsB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;QAElE;;WAEG;QACH,kBAAa,GAAG,CAAC,IAAS,EAAE,cAAmD,EAAiB,EAAE,CAChG,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;QAEzD;;WAEG;QACH,wBAAmB,GAAG,CAAC,IAAY,EAAE,OAAe,EAAmD,EAAE,CACvG,IAAA,gBAAQ,EACN,+BAA+B,OAAO,EAAE,EACxC,IAAA,yBAAgB,EACd,IAAA,kBAAS,EACP,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,EACtD,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,iCAAwB,EAAC,mDAAmD,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAC/G,EACD,CAAC,EAAE,cAAc;QACjB,IAAI,CAAC,gBAAgB;SACtB,CACF,CAAA;QAEH;;WAEG;QACH,wBAAmB,GAAG,CACpB,IAAmB,EACnB,YAAiF,EAKjF,EAAE;YACF,MAAM,IAAI,GAAG,IAAI,CAAA;YACjB,OAAO,IAAA,gBAAQ,EACb,uBAAuB,IAAI,CAAC,EAAE,EAAE,EAChC,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,qCAAqC;gBACrC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAC9B,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,8BAA8B;gBAC9B,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;gBAEvC,iBAAiB;gBACjB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;gBAEtE,4BAA4B;gBAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,4BAAkB,CAAA;gBAC5C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,kCAAwB,CAAA;gBAEnD,mBAAmB;gBACnB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAChC,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EACzD,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAkB,EAAC,+CAA+C,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CACpG,CAAA;gBAED,yBAAyB;gBACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAA;gBAEhE,kCAAkC;gBAClC,MAAM,WAAW,GAAkB;oBACjC,GAAG,IAAI;oBACP,KAAK;oBACL,QAAQ;oBACR,MAAM,EAAE,OAAO;iBAChB,CAAA;gBAED,yBAAyB;gBACzB,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;gBAEzC,OAAO,WAAW,CAAA;YACpB,CAAC,CAAC,CACH,CAAA;QACH,CAAC,CAAA;QAED;;WAEG;QACH,iCAA4B,GAAG,CAC7B,IAAmB,EACnB,YAAiF,EAKjF,EAAE;YACF,OAAO,IAAA,gBAAQ,EACb,gCAAgC,IAAI,CAAC,EAAE,EAAE,EACzC,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,mDAAmD;gBACnD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC7C,OAAO,IAAI,CAAA;gBACb,CAAC;gBAED,8BAA8B;gBAC9B,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;gBAEvC,4BAA4B;gBAC5B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,4BAAkB,CAAA;gBAC5C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,kCAAwB,CAAA;gBAEnD,uCAAuC;gBACvC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAChC,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAC9D,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAkB,EAAC,0DAA0D,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAC/G,CAAA;gBAED,yBAAyB;gBACzB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAA;gBAEhE,kCAAkC;gBAClC,MAAM,WAAW,GAAkB;oBACjC,GAAG,IAAI;oBACP,QAAQ;oBACR,MAAM,EAAE,OAAO;iBAChB,CAAA;gBAED,yBAAyB;gBACzB,KAAK,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;gBAEzC,OAAO,WAAW,CAAA;YACpB,CAAC,CAAC,CACH,CAAA;QACH,CAAC,CAAA;QAED;;WAEG;QACH,gBAAW,GAAG,GAAkC,EAAE;YAChD,MAAM,IAAI,GAAG,IAAI,CAAA;YACjB,OAAO,IAAA,gBAAQ,EACb,2BAA2B,EAC3B,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,iDAAiD;gBACjD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAC3D,eAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EACtB,eAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,eAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAC7C,CAAA;gBACD,OAAO,MAAM,CAAA;YACf,CAAC,CAAC,CACH,CAAA;QACH,CAAC,CAAA;IA5J6D,CAAC;CA6JhE;AA9JD,0EA8JC;AAED;;GAEG;AACI,MAAM,+BAA+B,GAAG,GAI7C,EAAE,CACF,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,4BAAkB,CAAA;IAC5C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,kCAAwB,CAAA;IAEnD,qGAAqG;IACrG,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,CAAA;IAE/B,sFAAsF;IACtF,MAAM,iBAAiB,GAAG;QACxB,iBAAiB,EAAE,CAAC,SAAsB,EAAE,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC1G,cAAc,EAAE,CAAC,QAAgB,EAAE,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC7F,kBAAkB,EAAE,GAAG,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;QAC7E,kBAAkB,EAAE,GAAG,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;QAC7E,aAAa,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACjF,cAAc,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,eAAM,CAAC,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;KACpF,CAAA;IAED,MAAM,cAAc,GAAG,IAAI,gCAAc,CAAC,GAAG,EAAE,iBAAwB,CAAC,CAAA;IACxE,OAAO,IAAI,+BAA+B,CAAC,cAAc,CAAC,CAAA;AAC5D,CAAC,CAAC,CAAA;AAxBS,QAAA,+BAA+B,mCAwBxC;AAEJ;;GAEG;AACU,QAAA,+BAA+B,GAIxC,cAAK,CAAC,MAAM,CAAC,mCAA2B,EAAE,IAAA,uCAA+B,GAAE,CAAC,CAAA;AAEhF;;GAEG;AACU,QAAA,iCAAiC,GAAG,cAAK,CAAC,MAAM,CAC3D,mCAA2B,EAC3B,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,IAAA,uCAA+B,GAAE,CAAA;IAExD,yEAAyE;IACzE,KAAK,CAAC,CAAC,eAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,eAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAA;IAEjF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAC,CACH,CAAA;AAED;;GAEG;AAEH;;GAEG;AACI,MAAM,kBAAkB,GAAG,CAChC,KAAwB,EACxB,OAAe,EACf,WAAW,GAAG,CAAC,EACmF,EAAE;IACpG,MAAM,UAAU,GAAG,4BAAkB,CAAA;IACrC,OAAO,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,UAAU,CAAA;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAA;QAE5B,0DAA0D;QAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,eAAM,CAAC,GAAG,CACtC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAC5B,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,EACtC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,iCAAwB,EAAC,+BAA+B,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAC3F,CAAA;YAED,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAChC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EACpC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAkB,EAAC,wBAAwB,EAAE,OAAO,EAAE,KAAK,CAAC,CACxE,CAAA;YAED,OAAO,SAAS,CAAA;QAClB,CAAC,CAAC,CACH,EACD,EAAE,WAAW,EAAE,CAChB,CAAA;QAED,OAAO,cAAc,CAAA;IACvB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAhCY,QAAA,kBAAkB,sBAgC9B;AAED;;GAEG;AACI,MAAM,8BAA8B,GAAG,CAC5C,IAAY,EACZ,OAAe,EACf,YAA+C,EACwC,EAAE;IACzF,MAAM,UAAU,GAAG,4BAAkB,CAAA;IACrC,OAAO,eAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACzB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,UAAU,CAAA;QACjC,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAA;QAE5B,sBAAsB;QACtB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAChC,GAAG,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,EACtC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,iCAAwB,EAAC,+BAA+B,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,CAC3F,CAAA;QAED,sBAAsB;QACtB,MAAM,cAAc,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAE9C,kCAAkC;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,IAAA,kBAAS,EAChC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,EAAE,OAAO,CAAC,EAC7C,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,2BAAkB,EAAC,sCAAsC,EAAE,OAAO,EAAE,KAAK,CAAC,CACtF,CAAA;QAED,OAAO,SAAS,CAAA;IAClB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AA3BY,QAAA,8BAA8B,kCA2B1C"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect-based AudioPlayer service implementation
|
|
3
|
+
* Provides structured error handling and resource management for audio playback
|
|
4
|
+
*/
|
|
5
|
+
import { Context, Effect, Layer, Ref } from 'effect';
|
|
6
|
+
import { type PlaybackError } from '../errors';
|
|
7
|
+
/**
|
|
8
|
+
* Enhanced AudioPlayer service with Effect-based operations
|
|
9
|
+
*/
|
|
10
|
+
export interface EffectAudioPlayerService {
|
|
11
|
+
readonly playAudio: (filePath: string) => Promise<void>;
|
|
12
|
+
readonly playAudioEffect: (filePath: string) => Effect.Effect<void, PlaybackError>;
|
|
13
|
+
readonly playAudioWithTimeout: (filePath: string, timeoutMs: number) => Effect.Effect<void, PlaybackError>;
|
|
14
|
+
readonly playAudioWithRetry: (filePath: string, maxRetries?: number) => Effect.Effect<void, PlaybackError>;
|
|
15
|
+
readonly isPlaying: () => Effect.Effect<boolean, never>;
|
|
16
|
+
readonly stopPlayback: () => Effect.Effect<void, never>;
|
|
17
|
+
readonly healthCheck: () => Effect.Effect<boolean, never>;
|
|
18
|
+
readonly cleanup: () => Effect.Effect<void, never>;
|
|
19
|
+
}
|
|
20
|
+
export declare const EffectAudioPlayerContext: Context.Tag<EffectAudioPlayerService, EffectAudioPlayerService>;
|
|
21
|
+
/**
|
|
22
|
+
* Audio playback state for tracking
|
|
23
|
+
*/
|
|
24
|
+
interface AudioPlayerState {
|
|
25
|
+
readonly isPlaying: boolean;
|
|
26
|
+
readonly currentFilePath?: string;
|
|
27
|
+
readonly playbackStartTime?: Date;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Effect-based implementation of AudioPlayer service
|
|
31
|
+
*/
|
|
32
|
+
export declare class EffectAudioPlayerServiceImpl implements EffectAudioPlayerService {
|
|
33
|
+
private readonly playerState;
|
|
34
|
+
private readonly audioCommand;
|
|
35
|
+
constructor(playerState: Ref.Ref<AudioPlayerState>);
|
|
36
|
+
/**
|
|
37
|
+
* Traditional playAudio method (Promise-based)
|
|
38
|
+
*/
|
|
39
|
+
playAudio: (filePath: string) => Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Play audio with Effect-based error handling and state management
|
|
42
|
+
*/
|
|
43
|
+
playAudioEffect: (filePath: string) => Effect.Effect<void, PlaybackError>;
|
|
44
|
+
/**
|
|
45
|
+
* Play audio with timeout protection
|
|
46
|
+
*/
|
|
47
|
+
playAudioWithTimeout: (filePath: string, timeoutMs: number) => Effect.Effect<void, PlaybackError>;
|
|
48
|
+
/**
|
|
49
|
+
* Play audio with retry logic
|
|
50
|
+
*/
|
|
51
|
+
playAudioWithRetry: (filePath: string, maxRetries?: number) => Effect.Effect<void, PlaybackError>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if audio is currently playing
|
|
54
|
+
*/
|
|
55
|
+
isPlaying: () => Effect.Effect<boolean, never>;
|
|
56
|
+
/**
|
|
57
|
+
* Stop current playback (best effort, may not work on all platforms)
|
|
58
|
+
*/
|
|
59
|
+
stopPlayback: () => Effect.Effect<void, never>;
|
|
60
|
+
/**
|
|
61
|
+
* Health check to verify audio playback capabilities
|
|
62
|
+
*/
|
|
63
|
+
healthCheck: () => Effect.Effect<boolean, never>;
|
|
64
|
+
/**
|
|
65
|
+
* Clean up audio player resources
|
|
66
|
+
*/
|
|
67
|
+
cleanup: () => Effect.Effect<void, never>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create AudioPlayer service instance
|
|
71
|
+
*/
|
|
72
|
+
export declare const makeEffectAudioPlayerService: () => Effect.Effect<EffectAudioPlayerService, never>;
|
|
73
|
+
/**
|
|
74
|
+
* Layer providing Effect AudioPlayer service
|
|
75
|
+
*/
|
|
76
|
+
export declare const EffectAudioPlayerServiceLive: Layer.Layer<EffectAudioPlayerService, never>;
|
|
77
|
+
/**
|
|
78
|
+
* Scoped layer that automatically cleans up resources on scope close
|
|
79
|
+
*/
|
|
80
|
+
export declare const EffectAudioPlayerServiceScoped: Layer.Layer<EffectAudioPlayerService, never, never>;
|
|
81
|
+
/**
|
|
82
|
+
* Helper functions for audio playback workflows
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* Play multiple audio files in sequence
|
|
86
|
+
*/
|
|
87
|
+
export declare const playAudioSequence: (filePaths: readonly string[]) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
|
|
88
|
+
/**
|
|
89
|
+
* Play multiple audio files in parallel (useful for sound effects)
|
|
90
|
+
*/
|
|
91
|
+
export declare const playAudioParallel: (filePaths: readonly string[], concurrency?: number) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
|
|
92
|
+
/**
|
|
93
|
+
* Play audio with progress monitoring
|
|
94
|
+
*/
|
|
95
|
+
export declare const playAudioWithProgress: (filePath: string, onProgress?: (elapsed: number) => void) => Effect.Effect<void, PlaybackError, EffectAudioPlayerService>;
|
|
96
|
+
/**
|
|
97
|
+
* Create a managed audio player that automatically stops on scope exit
|
|
98
|
+
*/
|
|
99
|
+
export declare const withManagedAudioPlayer: <A, E>(program: Effect.Effect<A, E, EffectAudioPlayerService>) => Effect.Effect<A, E, EffectAudioPlayerService>;
|
|
100
|
+
export {};
|
|
101
|
+
//# sourceMappingURL=audio-player-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-player-service.d.ts","sourceRoot":"","sources":["../../../src/effect/services/audio-player-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Effect-based AudioPlayer service implementation
|
|
4
|
+
* Provides structured error handling and resource management for audio playback
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.withManagedAudioPlayer = exports.playAudioWithProgress = exports.playAudioParallel = exports.playAudioSequence = exports.EffectAudioPlayerServiceScoped = exports.EffectAudioPlayerServiceLive = exports.makeEffectAudioPlayerService = exports.EffectAudioPlayerServiceImpl = exports.EffectAudioPlayerContext = void 0;
|
|
8
|
+
const effect_1 = require("effect");
|
|
9
|
+
const effect_2 = require("effect");
|
|
10
|
+
const node_child_process_1 = require("node:child_process");
|
|
11
|
+
const errors_1 = require("../errors");
|
|
12
|
+
const utils_1 = require("../utils");
|
|
13
|
+
exports.EffectAudioPlayerContext = effect_1.Context.GenericTag('@voicevox/EffectAudioPlayer');
|
|
14
|
+
/**
|
|
15
|
+
* Cross-platform audio player utilities
|
|
16
|
+
*/
|
|
17
|
+
const detectPlatformAudioCommand = () => {
|
|
18
|
+
const platform = process.platform;
|
|
19
|
+
switch (platform) {
|
|
20
|
+
case 'darwin': // macOS
|
|
21
|
+
return {
|
|
22
|
+
command: 'afplay',
|
|
23
|
+
args: (filePath) => [filePath]
|
|
24
|
+
};
|
|
25
|
+
case 'win32': // Windows
|
|
26
|
+
return {
|
|
27
|
+
command: 'powershell',
|
|
28
|
+
args: (filePath) => [
|
|
29
|
+
'-Command',
|
|
30
|
+
`Add-Type -AssemblyName PresentationCore; $player = New-Object System.Windows.Media.MediaPlayer; $player.Open('file:///${filePath.replace(/\\/g, '/')}'); $player.Play(); while ($player.NaturalDuration.HasTimeSpan -eq $false) { Start-Sleep -Milliseconds 100 }; Start-Sleep -Milliseconds ($player.NaturalDuration.TimeSpan.TotalMilliseconds); $player.Close()`
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
default: // Linux and others
|
|
34
|
+
// Try different audio players in order of preference
|
|
35
|
+
const linuxPlayers = ['paplay', 'aplay', 'play', 'ffplay'];
|
|
36
|
+
for (const player of linuxPlayers) {
|
|
37
|
+
try {
|
|
38
|
+
// Simple check if command exists
|
|
39
|
+
require('child_process').execSync(`which ${player}`, { stdio: 'ignore' });
|
|
40
|
+
if (player === 'ffplay') {
|
|
41
|
+
return {
|
|
42
|
+
command: player,
|
|
43
|
+
args: (filePath) => ['-nodisp', '-autoexit', filePath]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
command: player,
|
|
48
|
+
args: (filePath) => [filePath]
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Fallback to aplay
|
|
56
|
+
return {
|
|
57
|
+
command: 'aplay',
|
|
58
|
+
args: (filePath) => [filePath]
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Effect-based implementation of AudioPlayer service
|
|
64
|
+
*/
|
|
65
|
+
class EffectAudioPlayerServiceImpl {
|
|
66
|
+
constructor(playerState) {
|
|
67
|
+
/**
|
|
68
|
+
* Traditional playAudio method (Promise-based)
|
|
69
|
+
*/
|
|
70
|
+
this.playAudio = (filePath) => {
|
|
71
|
+
return new Promise((resolve, reject) => {
|
|
72
|
+
const child = (0, node_child_process_1.spawn)(this.audioCommand.command, this.audioCommand.args(filePath), {
|
|
73
|
+
stdio: 'ignore',
|
|
74
|
+
windowsHide: true
|
|
75
|
+
});
|
|
76
|
+
child.on('close', (code) => {
|
|
77
|
+
if (code === 0) {
|
|
78
|
+
resolve();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
reject(new Error(`Audio playback failed with exit code ${code}`));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
child.on('error', (error) => {
|
|
85
|
+
reject(error);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Play audio with Effect-based error handling and state management
|
|
91
|
+
*/
|
|
92
|
+
this.playAudioEffect = (filePath) => {
|
|
93
|
+
const self = this;
|
|
94
|
+
return (0, utils_1.logTimed)(`playAudioEffect-${filePath}`, effect_1.Effect.gen(function* () {
|
|
95
|
+
// Update state to playing
|
|
96
|
+
yield* effect_1.Ref.update(self.playerState, (state) => ({
|
|
97
|
+
...state,
|
|
98
|
+
isPlaying: true,
|
|
99
|
+
currentFilePath: filePath,
|
|
100
|
+
playbackStartTime: new Date(),
|
|
101
|
+
}));
|
|
102
|
+
try {
|
|
103
|
+
// Perform the actual playback
|
|
104
|
+
yield* (0, errors_1.safeAsync)(() => self.playAudio(filePath), (error) => (0, errors_1.makePlaybackError)('Failed to play audio file', filePath, error));
|
|
105
|
+
// Update state to not playing
|
|
106
|
+
yield* effect_1.Ref.update(self.playerState, (state) => ({
|
|
107
|
+
...state,
|
|
108
|
+
isPlaying: false,
|
|
109
|
+
currentFilePath: undefined,
|
|
110
|
+
playbackStartTime: undefined,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// Ensure state is reset on error
|
|
115
|
+
yield* effect_1.Ref.update(self.playerState, (state) => ({
|
|
116
|
+
...state,
|
|
117
|
+
isPlaying: false,
|
|
118
|
+
currentFilePath: undefined,
|
|
119
|
+
playbackStartTime: undefined,
|
|
120
|
+
}));
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}));
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Play audio with timeout protection
|
|
127
|
+
*/
|
|
128
|
+
this.playAudioWithTimeout = (filePath, timeoutMs) => (0, utils_1.logTimed)(`playAudioWithTimeout-${filePath}-${timeoutMs}ms`, (0, utils_1.withTimeout)(this.playAudioEffect(filePath), effect_2.Duration.millis(timeoutMs)).pipe(effect_1.Effect.mapError((error) => error instanceof Error && error.message.includes('timeout')
|
|
129
|
+
? (0, errors_1.makePlaybackError)('Audio playback timed out', filePath, error)
|
|
130
|
+
: error)));
|
|
131
|
+
/**
|
|
132
|
+
* Play audio with retry logic
|
|
133
|
+
*/
|
|
134
|
+
this.playAudioWithRetry = (filePath, maxRetries = 3) => (0, utils_1.logTimed)(`playAudioWithRetry-${filePath}-retries-${maxRetries}`, (0, errors_1.retryWithJitter)(this.playAudioEffect(filePath), maxRetries, 500));
|
|
135
|
+
/**
|
|
136
|
+
* Check if audio is currently playing
|
|
137
|
+
*/
|
|
138
|
+
this.isPlaying = () => {
|
|
139
|
+
const self = this;
|
|
140
|
+
return effect_1.Ref.get(self.playerState).pipe(effect_1.Effect.map((state) => state.isPlaying));
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Stop current playback (best effort, may not work on all platforms)
|
|
144
|
+
*/
|
|
145
|
+
this.stopPlayback = () => {
|
|
146
|
+
const self = this;
|
|
147
|
+
return (0, utils_1.logTimed)('stopPlayback', effect_1.Effect.gen(function* () {
|
|
148
|
+
// Update state to not playing
|
|
149
|
+
yield* effect_1.Ref.update(self.playerState, (state) => ({
|
|
150
|
+
...state,
|
|
151
|
+
isPlaying: false,
|
|
152
|
+
currentFilePath: undefined,
|
|
153
|
+
playbackStartTime: undefined,
|
|
154
|
+
}));
|
|
155
|
+
// Note: Actual stopping of playback depends on platform and implementation
|
|
156
|
+
// This is mainly for state management
|
|
157
|
+
yield* effect_1.Effect.log('Playback stopped (state updated)');
|
|
158
|
+
}));
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Health check to verify audio playback capabilities
|
|
162
|
+
*/
|
|
163
|
+
this.healthCheck = () => {
|
|
164
|
+
const self = this;
|
|
165
|
+
return (0, utils_1.logTimed)('audioPlayerHealthCheck', effect_1.Effect.gen(function* () {
|
|
166
|
+
// Check if we can create an AudioPlayer instance without errors
|
|
167
|
+
const result = yield* effect_1.Effect.sync(() => {
|
|
168
|
+
try {
|
|
169
|
+
// Simple validation - check if audio command is available
|
|
170
|
+
return typeof self.audioCommand.command === 'string' && self.audioCommand.command.length > 0;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}).pipe(effect_1.Effect.catchAll(() => effect_1.Effect.succeed(false)));
|
|
176
|
+
return result;
|
|
177
|
+
}));
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Clean up audio player resources
|
|
181
|
+
*/
|
|
182
|
+
this.cleanup = () => {
|
|
183
|
+
const self = this;
|
|
184
|
+
return (0, utils_1.logTimed)('audioPlayerCleanup', effect_1.Effect.gen(function* () {
|
|
185
|
+
// Stop any current playback
|
|
186
|
+
yield* self.stopPlayback();
|
|
187
|
+
// Reset state
|
|
188
|
+
yield* effect_1.Ref.set(self.playerState, {
|
|
189
|
+
isPlaying: false,
|
|
190
|
+
currentFilePath: undefined,
|
|
191
|
+
playbackStartTime: undefined,
|
|
192
|
+
});
|
|
193
|
+
yield* effect_1.Effect.log('AudioPlayer service cleaned up');
|
|
194
|
+
}));
|
|
195
|
+
};
|
|
196
|
+
this.playerState = playerState;
|
|
197
|
+
this.audioCommand = detectPlatformAudioCommand();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
exports.EffectAudioPlayerServiceImpl = EffectAudioPlayerServiceImpl;
|
|
201
|
+
/**
|
|
202
|
+
* Create AudioPlayer service instance
|
|
203
|
+
*/
|
|
204
|
+
const makeEffectAudioPlayerService = () => effect_1.Effect.gen(function* () {
|
|
205
|
+
const playerState = yield* effect_1.Ref.make({
|
|
206
|
+
isPlaying: false,
|
|
207
|
+
currentFilePath: undefined,
|
|
208
|
+
playbackStartTime: undefined,
|
|
209
|
+
});
|
|
210
|
+
return new EffectAudioPlayerServiceImpl(playerState);
|
|
211
|
+
});
|
|
212
|
+
exports.makeEffectAudioPlayerService = makeEffectAudioPlayerService;
|
|
213
|
+
/**
|
|
214
|
+
* Layer providing Effect AudioPlayer service
|
|
215
|
+
*/
|
|
216
|
+
exports.EffectAudioPlayerServiceLive = effect_1.Layer.effect(exports.EffectAudioPlayerContext, (0, exports.makeEffectAudioPlayerService)());
|
|
217
|
+
/**
|
|
218
|
+
* Scoped layer that automatically cleans up resources on scope close
|
|
219
|
+
*/
|
|
220
|
+
exports.EffectAudioPlayerServiceScoped = effect_1.Layer.scoped(exports.EffectAudioPlayerContext, effect_1.Effect.gen(function* () {
|
|
221
|
+
const service = yield* (0, exports.makeEffectAudioPlayerService)();
|
|
222
|
+
// Add finalizer to cleanup resources when scope closes
|
|
223
|
+
yield* effect_1.Effect.addFinalizer(() => service.cleanup());
|
|
224
|
+
return service;
|
|
225
|
+
}));
|
|
226
|
+
/**
|
|
227
|
+
* Helper functions for audio playback workflows
|
|
228
|
+
*/
|
|
229
|
+
/**
|
|
230
|
+
* Play multiple audio files in sequence
|
|
231
|
+
*/
|
|
232
|
+
const playAudioSequence = (filePaths) => {
|
|
233
|
+
const playerService = exports.EffectAudioPlayerContext;
|
|
234
|
+
return effect_1.Effect.gen(function* () {
|
|
235
|
+
const service = yield* playerService;
|
|
236
|
+
// Play each file in sequence
|
|
237
|
+
for (const filePath of filePaths) {
|
|
238
|
+
yield* service.playAudioEffect(filePath);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
exports.playAudioSequence = playAudioSequence;
|
|
243
|
+
/**
|
|
244
|
+
* Play multiple audio files in parallel (useful for sound effects)
|
|
245
|
+
*/
|
|
246
|
+
const playAudioParallel = (filePaths, concurrency = 3) => {
|
|
247
|
+
const playerService = exports.EffectAudioPlayerContext;
|
|
248
|
+
return effect_1.Effect.gen(function* () {
|
|
249
|
+
const service = yield* playerService;
|
|
250
|
+
// Play all files in parallel with limited concurrency
|
|
251
|
+
yield* effect_1.Effect.all(filePaths.map((filePath) => service.playAudioEffect(filePath)), { concurrency });
|
|
252
|
+
});
|
|
253
|
+
};
|
|
254
|
+
exports.playAudioParallel = playAudioParallel;
|
|
255
|
+
/**
|
|
256
|
+
* Play audio with progress monitoring
|
|
257
|
+
*/
|
|
258
|
+
const playAudioWithProgress = (filePath, onProgress) => {
|
|
259
|
+
const playerService = exports.EffectAudioPlayerContext;
|
|
260
|
+
return effect_1.Effect.gen(function* () {
|
|
261
|
+
const service = yield* playerService;
|
|
262
|
+
if (!onProgress) {
|
|
263
|
+
return yield* service.playAudioEffect(filePath);
|
|
264
|
+
}
|
|
265
|
+
// Start playback in a fiber
|
|
266
|
+
const playbackFiber = yield* effect_1.Effect.fork(service.playAudioEffect(filePath));
|
|
267
|
+
// Monitor progress
|
|
268
|
+
const progressFiber = yield* effect_1.Effect.fork(effect_1.Effect.gen(function* () {
|
|
269
|
+
const startTime = Date.now();
|
|
270
|
+
while (true) {
|
|
271
|
+
const isPlaying = yield* service.isPlaying();
|
|
272
|
+
if (!isPlaying)
|
|
273
|
+
break;
|
|
274
|
+
const elapsed = Date.now() - startTime;
|
|
275
|
+
onProgress(elapsed);
|
|
276
|
+
yield* effect_1.Effect.sleep(effect_2.Duration.millis(100));
|
|
277
|
+
}
|
|
278
|
+
}));
|
|
279
|
+
// Wait for playback to complete
|
|
280
|
+
yield* effect_1.Fiber.await(playbackFiber);
|
|
281
|
+
// Interrupt progress monitoring
|
|
282
|
+
yield* effect_1.Fiber.interrupt(progressFiber);
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
exports.playAudioWithProgress = playAudioWithProgress;
|
|
286
|
+
/**
|
|
287
|
+
* Create a managed audio player that automatically stops on scope exit
|
|
288
|
+
*/
|
|
289
|
+
const withManagedAudioPlayer = (program) => {
|
|
290
|
+
const playerService = exports.EffectAudioPlayerContext;
|
|
291
|
+
return effect_1.Effect.gen(function* () {
|
|
292
|
+
const service = yield* playerService;
|
|
293
|
+
return yield* effect_1.Effect.acquireUseRelease(effect_1.Effect.void, () => program, () => service.stopPlayback());
|
|
294
|
+
});
|
|
295
|
+
};
|
|
296
|
+
exports.withManagedAudioPlayer = withManagedAudioPlayer;
|
|
297
|
+
//# sourceMappingURL=audio-player-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-player-service.js","sourceRoot":"","sources":["../../../src/effect/services/audio-player-service.ts"],"names":[],"mappings":"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"}
|