diff --git a/NestsUI-v2/package-lock.json b/NestsUI-v2/package-lock.json index 14f562c..8826eac 100644 --- a/NestsUI-v2/package-lock.json +++ b/NestsUI-v2/package-lock.json @@ -13,10 +13,10 @@ "@fontsource-variable/inter": "^5.2.6", "@getalby/sdk": "^5.1.1", "@hookform/resolvers": "^5.2.2", - "@moq/hang": "^0.2.0", - "@moq/lite": "^0.1.7", - "@moq/publish": "^0.2.3", - "@moq/watch": "^0.2.3", + "@moq/hang": "^0.2.7", + "@moq/lite": "^0.3.0", + "@moq/publish": "^0.2.11", + "@moq/watch": "^0.2.14", "@nostrify/nostrify": "^0.50.2", "@nostrify/react": "^0.3.0", "@radix-ui/react-accordion": "^1.2.0", @@ -1037,23 +1037,24 @@ "license": "LGPL-2.1" }, "node_modules/@moq/hang": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@moq/hang/-/hang-0.2.0.tgz", - "integrity": "sha512-uW5hGVWGPY7uFD3w3kt1CNafbB5bge4O5/vZm756SgejihHkmqcFjSUfgabXxIJCXMr/1qtDXOVwIUs8QILZng==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@moq/hang/-/hang-0.2.7.tgz", + "integrity": "sha512-HLPpzDLsUf1dFA1M6qJMuo3Qupbyq/aiaXagh0anTjhOIjMReTF0f34Rqz+OlDWXBD3U18sPixc/WBHCwBvc0Q==", "license": "(MIT OR Apache-2.0)", "dependencies": { "@kixelated/libavjs-webcodecs-polyfill": "^0.5.5", "@libav.js/variant-opus-af": "^6.8.8", - "@moq/lite": "^0.1.3", - "@moq/signals": "^0.1.3", + "@moq/loc": "^0.1.0", + "@moq/net": "^0.1.2", + "@moq/signals": "^0.1.7", "@svta/cml-iso-bmff": "^1.0.0-alpha.9", "zod": "^4.1.5" } }, "node_modules/@moq/hang/node_modules/@moq/signals": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.4.tgz", - "integrity": "sha512-5LFU51B/OjprssoCe170Axc90HBeIGje/pvJjeTi9rD9SZ61sflgIN8fLICJkp1LhM4jSLouEt88fcOgPpRaIg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.7.tgz", + "integrity": "sha512-Z45dKktZj1BLviWSXgZmtlePy02jx0H3cYp5+q9aYpDpb9k+v8shpjwBNNuTGxT4PUgxiQQFDY6YpKfLb54Xwg==", "license": "(MIT OR Apache-2.0)", "peerDependencies": { "@types/react": "^19.1.8", @@ -1061,6 +1062,9 @@ "solid-js": "^1.9.7" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react": { "optional": true }, @@ -1070,19 +1074,20 @@ } }, "node_modules/@moq/hang/node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@moq/hang/node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "optional": true, "peer": true, @@ -1090,24 +1095,113 @@ "node": ">=0.10.0" } }, - "node_modules/@moq/lite": { + "node_modules/@moq/json": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@moq/json/-/json-0.0.1.tgz", + "integrity": "sha512-a5ItbCQs/+4tvOmsAh7b2ziD+TfyXD84T5bzIPglxqOLQI+6QqR+4vFOdxXW4u8MfnFeQHMu4t32ErMyDW9q4A==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@moq/net": "^0.1.2", + "@moq/signals": "^0.1.7" + }, + "peerDependencies": { + "zod": "^4.0.0" + } + }, + "node_modules/@moq/json/node_modules/@moq/signals": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@moq/lite/-/lite-0.1.7.tgz", - "integrity": "sha512-28KiFT0l4aWxPg/dr5HRxgPcfYL7IQZsuDB+mlPX4fUH5tsYrMFXfI2LSBXDpdoOB6dcXqmgqrkTaDr2wE0IaA==", + "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.7.tgz", + "integrity": "sha512-Z45dKktZj1BLviWSXgZmtlePy02jx0H3cYp5+q9aYpDpb9k+v8shpjwBNNuTGxT4PUgxiQQFDY6YpKfLb54Xwg==", + "license": "(MIT OR Apache-2.0)", + "peerDependencies": { + "@types/react": "^19.1.8", + "react": "^19.0.0", + "solid-js": "^1.9.7" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "solid-js": { + "optional": true + } + } + }, + "node_modules/@moq/json/node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@moq/json/node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@moq/lite": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@moq/lite/-/lite-0.3.0.tgz", + "integrity": "sha512-mMLylv5KDxYiKAis9MIJaJXWRX/NyPqwrv5/ktXLZT8QPii4I+fysi9/CEF5g7IqgDP5+WjbVIxiheBx/+wyyw==", + "deprecated": "Renamed to @moq/net. See https://moq.dev", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@moq/net": "^0.1.0" + }, + "peerDependencies": { + "zod": "^4.0.0" + } + }, + "node_modules/@moq/loc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@moq/loc/-/loc-0.1.0.tgz", + "integrity": "sha512-8ouPBhoZU/vAaHCrcsi97zOw0BJX/rQbfUJ7Dx2/Cmao6c4knrAXl8EVjlwKM4HLjfa8xzPd4Lqxkfv7G4QyhA==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@moq/net": "^0.1.1" + } + }, + "node_modules/@moq/msf": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@moq/msf/-/msf-0.1.1.tgz", + "integrity": "sha512-+Fjw0r4U4FCZS4Lo+pb06+jZqXgMmInNdY7RIZs9M8kDYdkC9wi/hymdIOAcmwr6f1kF9fLNZ7Spfx8oEgcFSg==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@moq/net": "^0.1.2", + "zod": "^4.1.5" + } + }, + "node_modules/@moq/net": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@moq/net/-/net-0.1.2.tgz", + "integrity": "sha512-j8Eyu188n06RGWXIoarVFYPTWEq52WhdXVg3S0a3CGpXP0j5t0t2p9kUzUSgShdk4W6ItbvZ30mR+Ihwmuja0Q==", "license": "(MIT OR Apache-2.0)", "dependencies": { "@moq/qmux": "^0.0.6", - "@moq/signals": "^0.1.4", + "@moq/signals": "^0.1.7", "async-mutex": "^0.5.0" }, "peerDependencies": { - "zod": "^4.1.0" + "zod": "^4.0.0" } }, - "node_modules/@moq/lite/node_modules/@moq/signals": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.4.tgz", - "integrity": "sha512-5LFU51B/OjprssoCe170Axc90HBeIGje/pvJjeTi9rD9SZ61sflgIN8fLICJkp1LhM4jSLouEt88fcOgPpRaIg==", + "node_modules/@moq/net/node_modules/@moq/signals": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.7.tgz", + "integrity": "sha512-Z45dKktZj1BLviWSXgZmtlePy02jx0H3cYp5+q9aYpDpb9k+v8shpjwBNNuTGxT4PUgxiQQFDY6YpKfLb54Xwg==", "license": "(MIT OR Apache-2.0)", "peerDependencies": { "@types/react": "^19.1.8", @@ -1115,6 +1209,9 @@ "solid-js": "^1.9.7" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react": { "optional": true }, @@ -1123,20 +1220,21 @@ } } }, - "node_modules/@moq/lite/node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "node_modules/@moq/net/node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "csstype": "^3.2.2" } }, - "node_modules/@moq/lite/node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "node_modules/@moq/net/node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "optional": true, "peer": true, @@ -1145,21 +1243,21 @@ } }, "node_modules/@moq/publish": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@moq/publish/-/publish-0.2.3.tgz", - "integrity": "sha512-FKD7nGkKK5+Vrynq3W79W7hvrJizfG1s8SPT51ct+rspS80as9CzCMRUJCzO941fYm37+ScTjHyxgpZJkdBJIQ==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@moq/publish/-/publish-0.2.11.tgz", + "integrity": "sha512-Z/w8Jg54Zd7lDSHF7Ec4/JCwwpAXqGfz29JFVM8Qj7KrJM1nzYHePujOBcmS/JguYGkPX/A/ZDCc8UuoCvZ/9A==", "license": "(MIT OR Apache-2.0)", "dependencies": { - "@moq/hang": "^0.2.0", - "@moq/lite": "^0.1.5", - "@moq/signals": "^0.1.3", - "@moq/ui-core": "^0.1.0" + "@moq/hang": "^0.2.7", + "@moq/json": "^0.0.1", + "@moq/net": "^0.1.2", + "@moq/signals": "^0.1.7" } }, "node_modules/@moq/publish/node_modules/@moq/signals": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.4.tgz", - "integrity": "sha512-5LFU51B/OjprssoCe170Axc90HBeIGje/pvJjeTi9rD9SZ61sflgIN8fLICJkp1LhM4jSLouEt88fcOgPpRaIg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.7.tgz", + "integrity": "sha512-Z45dKktZj1BLviWSXgZmtlePy02jx0H3cYp5+q9aYpDpb9k+v8shpjwBNNuTGxT4PUgxiQQFDY6YpKfLb54Xwg==", "license": "(MIT OR Apache-2.0)", "peerDependencies": { "@types/react": "^19.1.8", @@ -1167,6 +1265,9 @@ "solid-js": "^1.9.7" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react": { "optional": true }, @@ -1175,29 +1276,21 @@ } } }, - "node_modules/@moq/publish/node_modules/@moq/ui-core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@moq/ui-core/-/ui-core-0.1.0.tgz", - "integrity": "sha512-DJNBpUNQDyh7Tou324fbJ5/pT08UPghH3OxcVdLEo9IQeX//8NiEzJwcX7iuacR32nzgdiBThIbIpeFa60U3/g==", - "license": "(MIT OR Apache-2.0)", - "peerDependencies": { - "@moq/signals": "^0.1.2" - } - }, "node_modules/@moq/publish/node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@moq/publish/node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "optional": true, "peer": true, @@ -1212,21 +1305,21 @@ "license": "(MIT OR Apache-2.0)" }, "node_modules/@moq/watch": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@moq/watch/-/watch-0.2.3.tgz", - "integrity": "sha512-niAxQdmsNO7ELYYW6XgsH3/dsdp1PHt6EBPH74sR1/bNBQtMC0soZRZjrUQatD9374+MSFL2+NpV61/m1uv1nA==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@moq/watch/-/watch-0.2.14.tgz", + "integrity": "sha512-mEvRncrxPpUbi+qfRdPYXNgBgyy6zmFhEnixd2IS5uKcK2VdHxQr35/c+yNYcN7Nu0g2k/OdBCqOcuAeSE1Rjw==", "license": "(MIT OR Apache-2.0)", "dependencies": { - "@moq/hang": "^0.2.0", - "@moq/lite": "^0.1.5", - "@moq/signals": "^0.1.3", - "@moq/ui-core": "^0.1.0" + "@moq/hang": "^0.2.7", + "@moq/msf": "^0.1.1", + "@moq/net": "^0.1.2", + "@moq/signals": "^0.1.7" } }, "node_modules/@moq/watch/node_modules/@moq/signals": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.4.tgz", - "integrity": "sha512-5LFU51B/OjprssoCe170Axc90HBeIGje/pvJjeTi9rD9SZ61sflgIN8fLICJkp1LhM4jSLouEt88fcOgPpRaIg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@moq/signals/-/signals-0.1.7.tgz", + "integrity": "sha512-Z45dKktZj1BLviWSXgZmtlePy02jx0H3cYp5+q9aYpDpb9k+v8shpjwBNNuTGxT4PUgxiQQFDY6YpKfLb54Xwg==", "license": "(MIT OR Apache-2.0)", "peerDependencies": { "@types/react": "^19.1.8", @@ -1234,6 +1327,9 @@ "solid-js": "^1.9.7" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, "react": { "optional": true }, @@ -1242,29 +1338,21 @@ } } }, - "node_modules/@moq/watch/node_modules/@moq/ui-core": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@moq/ui-core/-/ui-core-0.1.0.tgz", - "integrity": "sha512-DJNBpUNQDyh7Tou324fbJ5/pT08UPghH3OxcVdLEo9IQeX//8NiEzJwcX7iuacR32nzgdiBThIbIpeFa60U3/g==", - "license": "(MIT OR Apache-2.0)", - "peerDependencies": { - "@moq/signals": "^0.1.2" - } - }, "node_modules/@moq/watch/node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "csstype": "^3.2.2" } }, "node_modules/@moq/watch/node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "optional": true, "peer": true, diff --git a/NestsUI-v2/package.json b/NestsUI-v2/package.json index ea83f32..09d4ca1 100644 --- a/NestsUI-v2/package.json +++ b/NestsUI-v2/package.json @@ -15,10 +15,10 @@ "@fontsource-variable/inter": "^5.2.6", "@getalby/sdk": "^5.1.1", "@hookform/resolvers": "^5.2.2", - "@moq/hang": "^0.2.0", - "@moq/lite": "^0.1.7", - "@moq/publish": "^0.2.3", - "@moq/watch": "^0.2.3", + "@moq/hang": "^0.2.7", + "@moq/lite": "^0.3.0", + "@moq/publish": "^0.2.11", + "@moq/watch": "^0.2.14", "@nostrify/nostrify": "^0.50.2", "@nostrify/react": "^0.3.0", "@radix-ui/react-accordion": "^1.2.0", diff --git a/NestsUI-v2/src/transport/moq-transport.ts b/NestsUI-v2/src/transport/moq-transport.ts index 42c9b54..013877f 100644 --- a/NestsUI-v2/src/transport/moq-transport.ts +++ b/NestsUI-v2/src/transport/moq-transport.ts @@ -82,7 +82,8 @@ export class MoQAudioTransport implements NestTransport { } get localAudioTrack(): MediaStreamTrack | undefined { - return this.microphone?.source.peek() ?? undefined; + const source = this.microphone?.source.peek(); + return source ? Publish.Audio.normalizeSource(source).track : undefined; } getRemoteAudioNode(pubkey: string): AudioNode | undefined { @@ -240,8 +241,9 @@ export class MoQAudioTransport implements NestTransport { }); // Log when mic source becomes available - this.micSourceDispose = this.microphone.source.subscribe((track) => { - if (track) { + this.micSourceDispose = this.microphone.source.subscribe((source) => { + if (source) { + const track = Publish.Audio.normalizeSource(source).track; console.log("[transport] microphone track acquired:", track.label); } else { console.log("[transport] microphone track: none"); @@ -459,8 +461,8 @@ export class MoQAudioTransport implements NestTransport { }); // Set up audio pipeline: source -> decoder -> emitter (speaker) - // Use a generous jitter buffer (150ms) to reduce audio underflow warnings - const sync = new Watch.Sync({ jitter: 150 as Moq.Time.Milli }); + // Use a generous fixed jitter buffer (150ms) to reduce audio underflow warnings + const sync = new Watch.Sync({ latency: 150 as Moq.Time.Milli }); const audioSource = new Watch.Audio.Source(sync, { broadcast }); const decoder = new Watch.Audio.Decoder(audioSource, { enabled: true }); const emitter = new Watch.Audio.Emitter(decoder, {