diff --git a/README.md b/README.md
index bb3857d..596dd6c 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# 🚀 EveFlow — Compagnon de Bureau Rétro-Futuriste 3D
[](https://github.com/R0m1k3/EveFlow)
-[](https://github.com/R0m1k3/EveFlow/releases/tag/v1.0.7)
+[](https://github.com/R0m1k3/EveFlow/releases/tag/v1.0.8)
[](LICENSE)
**EveFlow** est un compagnon de bureau Windows immersif haut de gamme, combinant une esthétique cyberpunk rétro-futuriste soignée et des technologies d'intelligence artificielle avancées. Il intègre un assistant virtuel en 3D nommé **Eve**, animé en temps réel avec des expressions émotionnelles dynamiques et synchronisé avec des services de synthèse vocale (TTS/STT) locaux et des architectures multi-agents.
@@ -74,7 +74,7 @@ Pour générer l'exécutable d'installation Windows (`.exe`) autonome :
```bash
npm run dist
```
- *L'exécutable d'installation NSIS (`EveFlow Setup 1.0.7.exe`) et la build décompressée seront générés dans le dossier `./out/`.*
+ *L'exécutable d'installation NSIS (`EveFlow Setup 1.0.8.exe`) et la build décompressée seront générés dans le dossier `./out/`.*
---
diff --git a/main.js b/main.js
index 3d3148c..64c677d 100644
--- a/main.js
+++ b/main.js
@@ -275,6 +275,13 @@ app.whenReady().then(() => {
callback(false);
});
+ session.defaultSession.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
+ if (permission === 'media') {
+ return true;
+ }
+ return false;
+ });
+
startWebhookServer();
createWindow();
diff --git a/package-lock.json b/package-lock.json
index bc9d947..2f2ed6d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "eveflow",
- "version": "1.0.7",
+ "version": "1.0.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "eveflow",
- "version": "1.0.7",
+ "version": "1.0.8",
"dependencies": {
"@react-three/drei": "^9.105.0",
"@react-three/fiber": "^8.16.0",
diff --git a/package.json b/package.json
index 9c59c2c..49ea6b1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "eveflow",
- "version": "1.0.7",
+ "version": "1.0.8",
"description": "Retro-futuristic Windows companion with 3D Eve bot, local TTS/STT, and multi-agent connectivity",
"main": "main.js",
"scripts": {
diff --git a/src/App.tsx b/src/App.tsx
index aaf291e..1e10539 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2543,6 +2543,27 @@ export const App: React.FC = () => {
+ {errorMessage && (
+
+
+
+ DÉFAILLANCE:
+ {errorMessage}
+
+
+ )}
+
{/* Barre de saisie compacte */}
{
@@ -699,14 +729,19 @@ export class AudioService {
// Fonctions utilitaires pour générer le conteneur WAV PCM 16-bit
private exportWAV(channelData: Float32Array[], recordingLength: number, sampleRate: number): Blob {
- const buffer = this.mergeBuffers(channelData, recordingLength);
- const wavBuffer = new ArrayBuffer(44 + buffer.length * 2);
+ const originalBuffer = this.mergeBuffers(channelData, recordingLength);
+
+ // Rééchantillonner à 16000 Hz pour la compatibilité avec l'API ASR (Whisper / Qwen3-ASR)
+ const targetSampleRate = 16000;
+ const resampledBuffer = this.downsampleBuffer(originalBuffer, sampleRate, targetSampleRate);
+
+ const wavBuffer = new ArrayBuffer(44 + resampledBuffer.length * 2);
const view = new DataView(wavBuffer);
/* Identifiant RIFF */
this.writeString(view, 0, 'RIFF');
/* Taille du fichier */
- view.setUint32(4, 36 + buffer.length * 2, true);
+ view.setUint32(4, 36 + resampledBuffer.length * 2, true);
/* Type RIFF */
this.writeString(view, 8, 'WAVE');
/* Identifiant format fmt */
@@ -718,9 +753,9 @@ export class AudioService {
/* Nombre de canaux (1 = Mono) */
view.setUint16(22, 1, true);
/* Fréquence d'échantillonnage */
- view.setUint32(24, sampleRate, true);
- /* Débit d'octets (sampleRate * blockAlign) */
- view.setUint32(28, sampleRate * 2, true);
+ view.setUint32(24, targetSampleRate, true);
+ /* Débit d'octets (targetSampleRate * blockAlign) */
+ view.setUint32(28, targetSampleRate * 2, true);
/* Block align (1 canal * 2 octets par échantillon) */
view.setUint16(32, 2, true);
/* Bits par échantillon (16 bits) */
@@ -728,13 +763,49 @@ export class AudioService {
/* Identifiant de données data */
this.writeString(view, 36, 'data');
/* Longueur des données audio */
- view.setUint32(40, buffer.length * 2, true);
+ view.setUint32(40, resampledBuffer.length * 2, true);
- this.floatTo16BitPCM(view, 44, buffer);
+ this.floatTo16BitPCM(view, 44, resampledBuffer);
return new Blob([view], { type: 'audio/wav' });
}
+ private downsampleBuffer(buffer: Float32Array, originalSampleRate: number, targetSampleRate: number): Float32Array {
+ if (originalSampleRate === targetSampleRate) {
+ return buffer;
+ }
+
+ const sampleRateRatio = originalSampleRate / targetSampleRate;
+ const newLength = Math.round(buffer.length / sampleRateRatio);
+ const result = new Float32Array(newLength);
+
+ let offsetResult = 0;
+ let offsetBuffer = 0;
+
+ while (offsetResult < result.length) {
+ const nextOffsetBuffer = Math.round((offsetResult + 1) * sampleRateRatio);
+
+ // Moyennage simple (box filter) pour éviter l'aliasing
+ let accum = 0;
+ let count = 0;
+ for (let i = offsetBuffer; i < nextOffsetBuffer && i < buffer.length; i++) {
+ accum += buffer[i];
+ count++;
+ }
+
+ if (count > 0) {
+ result[offsetResult] = accum / count;
+ } else {
+ result[offsetResult] = buffer[Math.min(offsetBuffer, buffer.length - 1)];
+ }
+
+ offsetResult++;
+ offsetBuffer = nextOffsetBuffer;
+ }
+
+ return result;
+ }
+
private mergeBuffers(channelData: Float32Array[], recordingLength: number): Float32Array {
const result = new Float32Array(recordingLength);
let offset = 0;