{"_id":"@azversan/mediasoup","_rev":"11-57b5973aad909403f875a22ca8c6c85e","name":"@azversan/mediasoup","dist-tags":{"alpha":"0.0.2-alpha.1","beta":"0.0.2-beta.0","latest":"1.3.1"},"versions":{"0.0.2-alpha.0":{"name":"@azversan/mediasoup","version":"0.0.2-alpha.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@0.0.2-alpha.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"70cdaad944200359163afd55b69a2f55702171b7","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-0.0.2-alpha.0.tgz","fileCount":9,"integrity":"sha512-nn2v8IKRj1U8tvHK1yyjCcCm3BiJjhDkMhOUzg3r7Nn2dGrtNTG8YhbiuAUuFjTVEughspPugMz6a0loSNTEww==","signatures":[{"sig":"MEQCIGK93ojv6A0SDatY24cIGIZF65MrRW91/uIhLKeUHAv7AiBeIUlIlXSJzYPvKkJKsLlpAvMP9xVD7aL9Nevb5QCO6Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":365359},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"cea9dfb5e720cf09a47c259b8fd7b15f3efe1a4b","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"An open-source NestJS Mediasoup module maintained by Azversan","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_0.0.2-alpha.0_1780184564278_0.9318022181888925","host":"s3://npm-registry-packages-npm-production"}},"0.0.2-alpha.1":{"name":"@azversan/mediasoup","version":"0.0.2-alpha.1","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@0.0.2-alpha.1","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"1b4606cdaacd6b48c39cbb03c826cb248c633c33","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-0.0.2-alpha.1.tgz","fileCount":9,"integrity":"sha512-1sNtd30onmwEHL24FOVW0uY6AVPK43acudvdTqa5nqvFpBPP13d6ZF9p3P6e1cbBV8lR5KQEB/2799guDUp+vA==","signatures":[{"sig":"MEYCIQDtQXTMQBu09g4LzDSFjFsKtU3ZTQvt0V/kktRjbP+L4AIhAN5jfLawfPE6PyUcr5QNJVTChVnpmtZ2+kfMSqbIL4yS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":435481},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"adc2fe94fe9d5636ac64a9842b6818ecf13417c6","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"An open-source NestJS Mediasoup module maintained by Azversan","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_0.0.2-alpha.1_1780955736650_0.44179907934069496","host":"s3://npm-registry-packages-npm-production"}},"0.0.2-beta.0":{"name":"@azversan/mediasoup","version":"0.0.2-beta.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@0.0.2-beta.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"a87ade19e8be8552b2a39a160acbcda0d30957c4","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-0.0.2-beta.0.tgz","fileCount":9,"integrity":"sha512-HDsJhxnYToiv+zuJXsGfnm4h5R4ArtAPlfiC3+GoiwZ2ZUQgEK0aduZ6OYzay52bnb/+/UbW8OHO3Ba233HD5Q==","signatures":[{"sig":"MEUCIAfYZBK5wAyaFrdKuAS1eeINLXuajGSCzOv+n25ZldKjAiEAldK03/uVwSAH1xPBDiVQwLnhEIdkbbfyFnuyvxhWrto=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":434085},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"820f8a4e8cb588c08dd9cf36e33a88762e6abf01","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_0.0.2-beta.0_1781243553435_0.9996614251934104","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@azversan/mediasoup","version":"1.0.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@1.0.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"4f74e8cf1063447be11e9a74064c53893aab5705","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.0.0.tgz","fileCount":9,"integrity":"sha512-h2urqnBD38AHo0mj4nuMVQgZUkbLDO2lXfV+26/NEs+UYIJPU09VxBivOjkya4MIWu5zm6lBfcjhrUDW87oeKA==","signatures":[{"sig":"MEUCIAwfJeR/IScIQ6eOTrk/neLvkGmkNf2MRFaI+6XZKaIYAiEA4cxWcPNEWXB4xAFFg05UFi3HyInf42pa3cELvQl4bug=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":433960},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"9ff9a043e5e91a1d9257ce68fdf70ae393039bf3","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_1.0.0_1781328483689_0.3129208203207543","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@azversan/mediasoup","version":"1.1.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@1.1.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"9af4a78d9ce2c7e0bba9820f1981b5dc0d1b0d2d","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.1.0.tgz","fileCount":9,"integrity":"sha512-PRRvlLWZhWPyW3KpB82ExG/p3GimNkmBaTijYlx+XqlmQm0TgKeBIql/gpskiJO7bgNr679fz+0t+XBYi+Nm8Q==","signatures":[{"sig":"MEYCIQDv/iMSJWzTixAUdVeqCVg3w94tnhDFpKo4mJtZkzh0EgIhALIO+wYeE8MCZ7s1vuidAfyXj0xYItj7Uy1U3Aen8X8V","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":432809},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"8c7e9a2162b5c9df09b011c4ae7733430c03d20f","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_1.1.0_1781985796306_0.06649917533769156","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@azversan/mediasoup","version":"1.2.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@1.2.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"890b3c0ed53f7c393d93d6a8f6adbd670b5d89b6","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.2.0.tgz","fileCount":9,"integrity":"sha512-ZdBt13ALKKBC2BnVubPLSd8Wq650KaoBiEXwPupZ5vA3JbGrsZpWdLdBemEHyLmCYqdZ98k06Ut9+Ud5YZ5fOw==","signatures":[{"sig":"MEYCIQDVxstlY05SpkJk6eG9lSLmvG7gP9iWCu5DSVW/CQYuYAIhAOlntA41SHBI3AAIX5tj/yN0MNqzC8xsG28d4msxrE3L","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":430105},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"a6e0f750f534dd51335b51bdeb2f2743a33c42e4","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^9.18.0","globals":"^16.0.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^9.18.0","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_1.2.0_1782601465186_0.4755186034069574","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@azversan/mediasoup","version":"1.2.1","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@1.2.1","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"a95bb7d1a7f1763599523363130278dccb1c7c20","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.2.1.tgz","fileCount":7,"integrity":"sha512-BDxFKEUlaaTqc0hNm4gjWuimNJNKGLG9ifaukpVQFrWuzVWzCP+SAjgrZH+b/l8iyBQf7ZvpUPXt5B24DnRokg==","signatures":[{"sig":"MEQCIFdbGYU1zpABcB6tmVxNEraKiICIdiJXhTWuiauUBcODAiAR7SKsWDAT1eX9STF5NSEX3NkMChAE5+y9A4A+M72hUw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":154904},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"68dd7b4f9c68f483cd9a4d60a31dac71bc352687","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\" --fix","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","test:cov":"jest --coverage","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.14.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"packageManager":"pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c","devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^10.8.0","globals":"^17.8.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^10.0.1","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^22.0.0","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_1.2.1_1785801523745_0.06110820155092367","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@azversan/mediasoup","version":"1.3.0","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","_id":"@azversan/mediasoup@1.3.0","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"dist":{"shasum":"a07288348f45c1a0732b2a525f2500d127342400","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.3.0.tgz","fileCount":7,"integrity":"sha512-4Ymu2x52ItHS+RuFe4acIb5lsUeJdvFC8yNwEP9LmIvu+tlxQCKO8cNyWdc+Qy8Q+6DFXdM45IeKOguGqAgBBA==","signatures":[{"sig":"MEUCIQChQmNYzT3Xpmdy1F5Exne1X87mSvGPxJkVWk0q2ULe5QIgA8v0hooCrpM7KvEmfNkkoRcpVQ0uzmGn+5Ea0Io++1Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":161941},"jest":{"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"},"coverageDirectory":"../coverage","collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"moduleFileExtensions":["js","json","ts"]},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"108dc48c8e510dfaf6a9da439d64736590841162","private":false,"scripts":{"lint":"eslint \"src/**/*.ts\"","test":"jest","build":"tsup","format":"prettier --write \"src/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" --fix","test:cov":"jest --coverage","typecheck":"tsc --noEmit","test:watch":"jest --watch","build:watch":"tsup --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"repository":{"url":"git+https://github.com/azversan/mediasoup-module.git","type":"git"},"_npmVersion":"11.19.0","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","directories":{},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"packageManager":"pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c","devDependencies":{"jest":"^30.4.2","tsup":"^8.5.1","eslint":"^10.8.0","globals":"^17.8.0","ts-jest":"^29.4.9","prettier":"^3.4.2","@swc/core":"^1.15.33","mediasoup":"^3.19.22","@eslint/js":"^10.0.1","typescript":"^6.0.0","@types/jest":"^30.0.0","@types/node":"^26.1.2","@nestjs/core":"^11.0.1","@nestjs/common":"^11.0.1","@nestjs/testing":"^11.0.1","reflect-metadata":"^0.2.2","typescript-eslint":"^8.20.0","@nestjs/event-emitter":"^3.1.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2"},"peerDependencies":{"mediasoup":"^3.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/common":"^10.0.0 || ^11.0.0","reflect-metadata":"^0.1.14 || ^0.2.0","@nestjs/event-emitter":"^3.1.0"},"_npmOperationalInternal":{"tmp":"tmp/mediasoup_1.3.0_1788006667239_0.547833122484221","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@azversan/mediasoup","version":"1.3.1","description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","private":false,"repository":{"type":"git","url":"git+https://github.com/azversan/mediasoup-module.git"},"homepage":"https://github.com/azversan/mediasoup-module","bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsup","build:watch":"tsup --watch","format":"prettier --write \"src/**/*.ts\"","lint":"eslint \"src/**/*.ts\"","lint:fix":"eslint \"src/**/*.ts\" --fix","typecheck":"tsc --noEmit","test":"jest","test:watch":"jest --watch","test:cov":"jest --coverage","prepublishOnly":"pnpm build"},"lint-staged":{"*.{js,ts}":["prettier --write --ignore-unknown","eslint --fix"],"*.{json,yml,yaml}":["prettier --write --ignore-unknown"]},"peerDependencies":{"@nestjs/common":"^10.0.0 || ^11.0.0","@nestjs/core":"^10.0.0 || ^11.0.0","@nestjs/event-emitter":"^3.1.0","mediasoup":"^3.0.0","reflect-metadata":"^0.1.14 || ^0.2.0"},"devDependencies":{"@eslint/js":"^10.0.1","@nestjs/common":"^11.0.1","@nestjs/core":"^11.0.1","@nestjs/event-emitter":"^3.1.0","@nestjs/testing":"^11.0.1","@swc/core":"^1.15.33","@types/jest":"^30.0.0","@types/node":"^26.1.2","eslint":"^10.8.0","eslint-config-prettier":"^10.0.1","eslint-plugin-prettier":"^5.2.2","globals":"^17.8.0","jest":"^30.4.2","mediasoup":"^3.19.22","prettier":"^3.4.2","reflect-metadata":"^0.2.2","ts-jest":"^29.4.9","tsup":"^8.5.1","typescript":"^6.0.0","typescript-eslint":"^8.20.0"},"jest":{"moduleFileExtensions":["js","json","ts"],"rootDir":"src","testRegex":".*\\.spec\\.ts$","transform":{"^.+\\.(t|j)s$":"ts-jest"},"collectCoverageFrom":["**/*.(t|j)s","!**/index.ts"],"coverageDirectory":"../coverage","testEnvironment":"node","moduleNameMapper":{"^@/(.*)$":"<rootDir>/$1"}},"packageManager":"pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c","gitHead":"6a2cf712c731139685e52d345823416daf67f1c7","_id":"@azversan/mediasoup@1.3.1","_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-xsrPK264gYtE2P6OVISO/it6VlbfHPc6Ex1exDf3V+rpPrwgHeYx2w2MVeestamTDrFyr/ZAmpd+wUzA+pHoXg==","shasum":"4367dc5772c25eab461393e6f6ccaec019afad4c","tarball":"https://registry.npmjs.org/@azversan/mediasoup/-/mediasoup-1.3.1.tgz","fileCount":7,"unpackedSize":161938,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHC68Iyi8y8NSKhIwO12PY/KM4qOi9qHE2irQkCCUtSuAiEA6XcAlpaC0PHmEFg4uDzJYp0r7OtpKFCQqDGXz8TwkFg="}]},"_npmUser":{"name":"agoenks29d","email":"agungmasda29@gmail.com"},"directories":{},"maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mediasoup_1.3.1_1788174009748_0.9674439624982525"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-30T23:42:44.073Z","modified":"2026-08-31T11:00:10.054Z","0.0.2-alpha.0":"2026-05-30T23:42:44.485Z","0.0.2-alpha.1":"2026-06-08T21:55:36.872Z","0.0.2-beta.0":"2026-06-12T05:52:33.574Z","1.0.0":"2026-06-13T05:28:03.866Z","1.1.0":"2026-06-20T20:03:16.438Z","1.2.0":"2026-06-27T23:04:25.332Z","1.2.1":"2026-08-03T23:58:43.904Z","1.3.0":"2026-08-29T12:31:07.381Z","1.3.1":"2026-08-31T11:00:09.883Z"},"bugs":{"url":"https://github.com/azversan/mediasoup-module/issues"},"author":{"name":"Agung Dirgantara","email":"agungmasda29@gmail.com"},"license":"MIT","homepage":"https://github.com/azversan/mediasoup-module","repository":{"type":"git","url":"git+https://github.com/azversan/mediasoup-module.git"},"description":"NestJS integration module for mediasoup WebRTC SFU — manages Workers, Routers, Transports, Producers, Consumers, and RTP Observers with type-safe event observability via NestJS EventEmitter","maintainers":[{"name":"agoenks29d","email":"agungmasda29@gmail.com"}],"readme":"# @azversan/mediasoup\n\n> An open-source NestJS module for [mediasoup](https://mediasoup.org/) — a powerful WebRTC SFU (Selective Forwarding Unit) server framework.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![NestJS](https://img.shields.io/badge/NestJS-%5E10%20%7C%7C%20%5E11-red)](https://nestjs.com)\n[![mediasoup](https://img.shields.io/badge/mediasoup-%5E3.0.0-blue)](https://mediasoup.org)\n[![npm version](https://img.shields.io/npm/v/@azversan/mediasoup.svg)](https://www.npmjs.com/package/@azversan/mediasoup)\n[![npm downloads](https://img.shields.io/npm/dm/@azversan/mediasoup.svg)](https://www.npmjs.com/package/@azversan/mediasoup)\n\n---\n\n- [@azversan/mediasoup](#azversanmediasoup)\n  - [Overview](#overview)\n  - [Features](#features)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n  - [Quick Start](#quick-start)\n  - [Module Registration](#module-registration)\n    - [Synchronous Registration](#synchronous-registration)\n    - [Asynchronous Registration](#asynchronous-registration)\n  - [Configuration Reference](#configuration-reference)\n    - [`MediasoupModuleOptions`](#mediasoupmoduleoptions)\n    - [`WorkerSettings` (extended)](#workersettings-extended)\n  - [MediasoupService API](#mediasoupservice-api)\n    - [Error Handling](#error-handling)\n    - [Workers](#workers)\n    - [WebRTC Servers](#webrtc-servers)\n    - [Routers](#routers)\n    - [Transports](#transports)\n    - [Producers \\& Consumers](#producers--consumers)\n    - [Data Producers \\& Data Consumers](#data-producers--data-consumers)\n    - [RTP Observers](#rtp-observers)\n  - [Event System](#event-system)\n    - [Listening to Events](#listening-to-events)\n    - [Event Reference](#event-reference)\n  - [AppData Schemas](#appdata-schemas)\n    - [`WorkerAppData`](#workerappdata)\n    - [`RouterAppData`](#routerappdata)\n    - [`TransportAppData`](#transportappdata)\n    - [`ConsumerProducerAppData`](#consumerproducerappdata)\n  - [Architecture](#architecture)\n  - [Examples](#examples)\n    - [Full WebRTC SFU Flow](#full-webrtc-sfu-flow)\n    - [Active Speaker and Audio Level Detection](#active-speaker-and-audio-level-detection)\n  - [Contributing](#contributing)\n  - [License](#license)\n\n---\n\n## Overview\n\n`@azversan/mediasoup` wraps the native mediasoup library into a fully idiomatic NestJS dynamic module. It handles the lifecycle of Workers, Routers, Transports, Producers, Consumers, RTP Observers, and Data channels — while automatically publishing all mediasoup events onto the NestJS `EventEmitter2` bus, keeping your application code clean and decoupled.\n\n## Features\n\n- **Full mediasoup v3 support** — Workers, Routers, WebRtcTransport, PlainTransport, PipeTransport, DirectTransport, Producers, Consumers, DataProducers, DataConsumers, ActiveSpeakerObserver, AudioLevelObserver, and WebRtcServer.\n- **Round-robin worker load balancing** — automatic distribution of Routers across Workers.\n- **Resource telemetry** — per-worker and per-router usage counters updated in real time.\n- **Global EventEmitter2 bridge** — every mediasoup lifecycle event is translated into a strongly-typed NestJS event.\n- **`@OnMediasoup()` decorator** — concise event-listener decorator with full TypeScript inference.\n- **Sync & async module registration** — supports `useFactory`, `useClass`, and `useExisting` patterns.\n- **Global or scoped module** — register once and expose `MediasoupService` application-wide with `isGlobal: true`.\n\n## Requirements\n\n| Dependency              | Version                |\n| ----------------------- | ---------------------- |\n| Node.js                 | >= 22                  |\n| `@nestjs/common`        | `^10.0.0` or `^11.0.0` |\n| `@nestjs/core`          | `^10.0.0` or `^11.0.0` |\n| `@nestjs/event-emitter` | `^3.1.0`               |\n| `mediasoup`             | `^3.0.0`               |\n| `reflect-metadata`      | `^0.1.14` or `^0.2.0`  |\n\n## Installation\n\n```bash\nnpm install @azversan/mediasoup\n```\n\n## Quick Start\n\n```typescript\n// app.module.ts\nimport { Module } from '@nestjs/common';\nimport { MediasoupModule } from '@azversan/mediasoup';\n\n@Module({\n  imports: [\n    MediasoupModule.register(\n      {\n        workerSettings: {\n          logLevel: 'warn',\n          logTags: ['info', 'ice', 'dtls', 'rtp', 'srtp'],\n        },\n        mediaCodecs: [\n          {\n            kind: 'audio',\n            mimeType: 'audio/opus',\n            clockRate: 48000,\n            channels: 2,\n          },\n          {\n            kind: 'video',\n            mimeType: 'video/VP8',\n            clockRate: 90000,\n          },\n        ],\n        webRtcServer: { enable: false },\n      },\n      { isGlobal: true },\n    ),\n  ],\n})\nexport class AppModule {}\n```\n\n```typescript\n// room.service.ts\nimport { Injectable } from '@nestjs/common';\nimport { MediasoupService } from '@azversan/mediasoup';\n\n@Injectable()\nexport class RoomService {\n  constructor(private readonly mediasoup: MediasoupService) {}\n\n  async createRoom() {\n    const router = await this.mediasoup.createRouter();\n    return router.id;\n  }\n\n  async createSendTransport(routerId: string) {\n    return this.mediasoup.createWebRtcTransport(routerId, {\n      listenIps: [{ ip: '0.0.0.0', announcedIp: '192.168.1.100' }],\n      enableUdp: true,\n      enableTcp: true,\n    });\n  }\n}\n```\n\n## Module Registration\n\n### Synchronous Registration\n\n```typescript\nMediasoupModule.register(options: MediasoupModuleOptions, globalOptions?: MediasoupModuleGlobalOptions)\n```\n\n```typescript\nMediasoupModule.register(\n  {\n    workerSettings: { logLevel: 'warn', workerCount: 4 },\n    webRtcServer: { enable: false },\n  },\n  { isGlobal: true },\n);\n```\n\n### Asynchronous Registration\n\n```typescript\nMediasoupModule.registerAsync(asyncOptions: MediasoupModuleAsyncOptions)\n```\n\n**Using `useFactory`:**\n\n```typescript\nMediasoupModule.registerAsync({\n  isGlobal: true,\n  imports: [ConfigModule],\n  inject: [ConfigService],\n  useFactory: (config: ConfigService) => ({\n    workerSettings: {\n      logLevel: config.get('MEDIASOUP_LOG_LEVEL'),\n      workerCount: config.get<number>('MEDIASOUP_WORKER_COUNT'),\n    },\n    webRtcTransportOptions: {\n      listenIps: [{ ip: '0.0.0.0', announcedIp: config.get('ANNOUNCED_IP') }],\n      enableUdp: true,\n      enableTcp: true,\n    },\n    webRtcServer: { enable: false },\n  }),\n});\n```\n\n**Using `useClass`:**\n\n```typescript\n@Injectable()\nexport class MediasoupConfigService implements MediasoupOptionsFactory {\n  createMediasoupOptions(): MediasoupModuleOptions {\n    return {\n      workerSettings: { logLevel: 'warn' },\n      webRtcServer: { enable: false },\n    };\n  }\n}\n\nMediasoupModule.registerAsync({\n  useClass: MediasoupConfigService,\n});\n```\n\n## Configuration Reference\n\n### `MediasoupModuleOptions`\n\n| Field                    | Type                                                                    | Required | Description                                                                                                                                           |\n| ------------------------ | ----------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `workerSettings`         | `WorkerSettings`                                                        | ✅       | Settings passed to `mediasoup.createWorker()`. Includes optional `workerCount` (defaults to `Math.max(1, cpus - 1)`).                                 |\n| `mediaCodecs`            | `RouterRtpCodecCapability[]`                                            | ❌       | Default media codecs for all routers created via `createRouter()`.                                                                                    |\n| `webRtcServer`           | `{ enable: true; options: WebRtcServerOptions }` or `{ enable: false }` | ✅       | If enabled, a `WebRtcServer` is created per worker on bootstrap using port-offset strategy.                                                           |\n| `webRtcTransportOptions` | `Omit<WebRtcTransportOptions, 'appData'>`                               | ❌       | Default options merged into every `createWebRtcTransport()` call.                                                                                     |\n| `plainTransportOptions`  | `Omit<PlainTransportOptions, 'appData'>`                                | ❌       | Default options for `createPlainTransport()`.                                                                                                         |\n| `pipeTransportOptions`   | `Omit<PipeTransportOptions, 'appData'>`                                 | ❌       | Default options for `createPipeTransport()`.                                                                                                          |\n| `directTransportOptions` | `Omit<DirectTransportOptions, 'appData'>`                               | ❌       | Default options for `createDirectTransport()`.                                                                                                        |\n| `transportTrace`         | `{ enable: boolean; events: TransportTraceEventType[] }`                | ❌       | Enable trace events on all new transports.                                                                                                            |\n| `consumerTrace`          | `{ enable: boolean; events: ConsumerTraceEventType[] }`                 | ❌       | Enable trace events on all new consumers.                                                                                                             |\n| `producerTrace`          | `{ enable: boolean; events: ProducerTraceEventType[] }`                 | ❌       | Enable trace events on all new producers.                                                                                                             |\n| `exceptionFactory`       | `(exception: MediasoupException) => Error`                              | ❌       | Transforms every `MediasoupException` thrown by `MediasoupService` before it reaches the caller. Defaults to throwing the `MediasoupException` as-is. |\n\n### `WorkerSettings` (extended)\n\nAll native mediasoup `WorkerSettings` fields plus:\n\n| Field         | Type     | Default                 | Description                                       |\n| ------------- | -------- | ----------------------- | ------------------------------------------------- |\n| `workerCount` | `number` | `Math.max(1, cpus - 1)` | Number of Worker processes to spawn on bootstrap. |\n\n## MediasoupService API\n\nInject `MediasoupService` into any provider to access the full mediasoup resource API.\n\n```typescript\nconstructor(private readonly mediasoup: MediasoupService) {}\n```\n\n### Error Handling\n\nEvery `create*` method (`createWorker`, `createRouter`, `createWebRtcTransport`, `createConsumer`, etc.) normalizes failures into a **`MediasoupException`**:\n\n- If the underlying native mediasoup call fails (e.g. invalid codec, worker crash), the original error is wrapped into a `MediasoupException` with a descriptive message. The original error remains accessible via `.cause`.\n- If a `MediasoupException` is already thrown internally (e.g. a `getRouterById` lookup failing because the router doesn't exist), it is passed through unchanged — never double-wrapped.\n\n```typescript\ntry {\n  await this.mediasoup.createRouter({ worker: someClosedWorker });\n} catch (error) {\n  if (error instanceof MediasoupException) {\n    console.error(error.message); // e.g. \"Failed to create router\"\n    console.error(error.cause); // the original native error, if any\n  }\n}\n```\n\nTo transform exceptions before they reach your code (e.g. to map them into a NestJS `HttpException`), provide an `exceptionFactory` in the module options:\n\n```typescript\nMediasoupModule.register({\n  // ...\n  exceptionFactory: (exception) => new BadRequestException(exception.message),\n});\n```\n\n### Workers\n\n**`createWorker(settings?)`**\n\nSpawns a new mediasoup Worker process. If `webRtcServer.enable` is `true`, a `WebRtcServer` is automatically created on the worker.\n\n```typescript\nconst worker = await this.mediasoup.createWorker({ logLevel: 'debug' });\n```\n\n**`getWorkers(): Worker[]`**\n\nReturns all active Workers.\n\n**`getWorkerByPid(pid: number): Worker`**\n\nFinds a Worker by its OS Process ID. Throws `MediasoupException` if not found.\n\n**`getWorkerByRouterId(id: RouterId): Worker`**\n\nFinds the Worker hosting a specific Router.\n\n**`getRoundRobinWorker(exceptPid?: number | number[]): Worker`**\n\nReturns a Worker using round-robin load balancing. Optionally exclude specific PIDs.\n\n```typescript\n// Get any available worker\nconst worker = this.mediasoup.getRoundRobinWorker();\n\n// Exclude specific workers\nconst worker = this.mediasoup.getRoundRobinWorker([1234, 5678]);\n```\n\n### WebRTC Servers\n\n**`getWebRtcServers(): WebRtcServer[]`**\n\nReturns all active `WebRtcServer` instances.\n\n**`getWebRtcServerById(id: WebRtcServerId): WebRtcServer`**\n\nFinds a `WebRtcServer` by ID. Throws if not found.\n\n**`getWebRtcServersByWorkerPid(workerPid: number | number[]): WebRtcServer[]`**\n\nReturns all `WebRtcServer` instances belonging to specified Worker PID(s).\n\n### Routers\n\n**`createRouter(options?): Promise<Router>`**\n\nCreates a Router. Uses round-robin Worker selection by default.\n\n```typescript\n// Auto-select worker\nconst router = await this.mediasoup.createRouter();\n\n// Specific worker\nconst router = await this.mediasoup.createRouter({ worker: myWorker });\n\n// Exclude worker PIDs\nconst router = await this.mediasoup.createRouter({ exceptWorkerPid: [1234] });\n\n// Custom codecs\nconst router = await this.mediasoup.createRouter({\n  mediaCodecs: [{ kind: 'audio', mimeType: 'audio/opus', clockRate: 48000, channels: 2 }],\n});\n```\n\n**`getRouters(): Router[]`**\n\nReturns all active Routers.\n\n**`getRouterById(id: RouterId): Router`**\n\nFinds a Router by ID. Throws if not found.\n\n**`getRoutersByWorkerPid(workerPid: number): Router[]`**\n\nReturns all Routers on a specific Worker.\n\n### Transports\n\nAll transport creation methods merge module-level defaults with per-call overrides. The `appData` field is managed internally and should not be supplied.\n\n**`createWebRtcTransport(routerId, options?): Promise<WebRtcTransport>`**\n\n```typescript\nconst transport = await this.mediasoup.createWebRtcTransport(router.id, {\n  listenIps: [{ ip: '0.0.0.0', announcedIp: '1.2.3.4' }],\n  enableUdp: true,\n  enableTcp: true,\n  preferUdp: true,\n});\n```\n\n**`createPlainTransport(routerId, options?): Promise<PlainTransport>`**\n\nFor RTP/RTCP-based integrations (e.g. FFmpeg, GStreamer, SIP gateways).\n\n**`createPipeTransport(routerId, options?): Promise<PipeTransport>`**\n\nFor piping media between Routers (e.g. across different Workers or servers).\n\n**`createDirectTransport(routerId, options?): Promise<DirectTransport>`**\n\nFor intra-process media relaying without network overhead.\n\n**`getTransports(): Transport[]`**\n\nReturns all active Transports.\n\n**`getTransportById(id, type?)`**\n\n```typescript\n// Generic base type\nconst transport = this.mediasoup.getTransportById(id);\n\n// Typed variant\nconst webrtc = this.mediasoup.getTransportById(id, 'webrtc'); // WebRtcTransport\nconst plain = this.mediasoup.getTransportById(id, 'plain'); // PlainTransport\nconst pipe = this.mediasoup.getTransportById(id, 'pipe'); // PipeTransport\nconst direct = this.mediasoup.getTransportById(id, 'direct'); // DirectTransport\n```\n\nThrows `MediasoupException` if not found or type mismatch.\n\n**`getTransportsByRouterId(id, type?)`**\n\nReturns all transports on a Router, optionally filtered by type.\n\n### Producers & Consumers\n\n**`createProducer(transportId, kind, rtpParameters): Promise<Producer>`**\n\nSets the transport's `appData.direction` to `'send'`.\n\n```typescript\nconst producer = await this.mediasoup.createProducer(transportId, 'video', rtpParameters);\n```\n\n**`createConsumer(transportId, producerId, rtpCapabilities): **Promise<Consumer>`\n\nSets the transport's `appData.direction` to `'recv'`. Validates codec compatibility first.\n\n```typescript\nconst consumer = await this.mediasoup.createConsumer(transportId, producerId, peerRtpCapabilities);\n```\n\n**Getters**\n\n```typescript\nthis.mediasoup.getProducers(): Producer[]\nthis.mediasoup.getProducerById(id: string): Producer\nthis.mediasoup.getConsumers(): Consumer[]\nthis.mediasoup.getConsumerById(id: string): Consumer\n```\n\n### Data Producers & Data Consumers\n\n**`createDataProducer(transportId, options?): Promise<DataProducer>`**\n\n**`createDataConsumer(transportId, options): Promise<DataConsumer>`**\n\n**Getters**\n\n```typescript\nthis.mediasoup.getDataProducers(): DataProducer[]\nthis.mediasoup.getDataProducerById(id: DataProducerId): DataProducer\nthis.mediasoup.getDataConsumers(): DataConsumer[]\nthis.mediasoup.getDataConsumerById(id: DataConsumerId): DataConsumer\n```\n\n### RTP Observers\n\n**`createActiveSpeakerObserver(routerId, interval?): **Promise<ActiveSpeakerObserver>`\n\nMonitors audio streams to detect the dominant speaker.\n\n```typescript\nconst observer = await this.mediasoup.createActiveSpeakerObserver(router.id, 300);\n```\n\n**`createAudioLevelObserver(routerId, options?): Promise<AudioLevelObserver>`**\n\nReports per-producer audio volume levels.\n\n```typescript\nconst observer = await this.mediasoup.createAudioLevelObserver(router.id, {\n  maxEntries: 1,\n  threshold: -80,\n  interval: 800,\n});\n```\n\n**`getRtpObservers(type?)` / `getRtpObserverById(id)` / **`getRtpObserversByRouter(routerId, type?)`\n\n```typescript\n// All observers\nconst all = this.mediasoup.getRtpObservers();\n\n// Filtered by type\nconst audioLevel = this.mediasoup.getRtpObservers('audiolevel'); // AudioLevelObserver[]\nconst speaker = this.mediasoup.getRtpObservers('activespeaker'); // ActiveSpeakerObserver[]\n\n// By router\nconst routerObservers = this.mediasoup.getRtpObserversByRouter(routerId);\n```\n\n## Event System\n\n### Listening to Events\n\nUse the `@OnMediasoup()` decorator to subscribe to any mediasoup lifecycle event with full TypeScript type inference.\n\n```typescript\nimport { Injectable } from '@nestjs/common';\nimport { OnMediasoup, MediasoupEventData } from '@azversan/mediasoup';\n\n@Injectable()\nexport class MediaEventsService {\n  @OnMediasoup('WorkerCreated')\n  onWorkerCreated(data: MediasoupEventData<'WorkerCreated'>) {\n    console.log(`Worker spawned: PID ${data.pid}`);\n  }\n\n  @OnMediasoup('ProducerCreated')\n  onProducerCreated(data: MediasoupEventData<'ProducerCreated'>) {\n    console.log(`New producer: ${data.id}`);\n  }\n\n  @OnMediasoup('ConsumerLayersChange')\n  onLayersChange(data: MediasoupEventData<'ConsumerLayersChange'>) {\n    console.log(`Consumer ${data.id} layers:`, data.data);\n  }\n\n  @OnMediasoup('RtpObserverDominantSpeaker')\n  onDominantSpeaker(data: MediasoupEventData<'RtpObserverDominantSpeaker'>) {\n    console.log(`Dominant speaker changed:`, data.data.producer.id);\n  }\n}\n```\n\n`@OnMediasoup` is a thin wrapper over `@OnEvent` from `@nestjs/event-emitter`.\n\n### Event Reference\n\n**Worker Events**\n\n| Event                         | Payload                                  |\n| ----------------------------- | ---------------------------------------- |\n| `WorkerCreated`               | `{ pid }`                                |\n| `WorkerClose`                 | `{ pid }`                                |\n| `WorkerDied`                  | `{ pid, data: { error } }`               |\n| `WorkerSubProcessClose`       | `{ pid }`                                |\n| `WorkerListenerError`         | `{ pid, data: { event, error } }`        |\n| `WorkerResourceUsageAdjusted` | `{ pid, data: { action, type, count } }` |\n\n**Router Events**\n\n| Event                         | Payload                                 |\n| ----------------------------- | --------------------------------------- |\n| `RouterCreated`               | `{ id }`                                |\n| `RouterClose`                 | `{ id }`                                |\n| `RouterWorkerClose`           | `{ id }`                                |\n| `RouterListenerError`         | `{ id, data: { event, error } }`        |\n| `RouterResourceUsageAdjusted` | `{ id, data: { action, type, count } }` |\n\n**Transport Events**\n\n| Event                           | Payload                                 |\n| ------------------------------- | --------------------------------------- |\n| `TransportCreated`              | `{ id }`                                |\n| `TransportClose`                | `{ id }`                                |\n| `TransportRouterClose`          | `{ id }`                                |\n| `TransportListenServerClose`    | `{ id }`                                |\n| `TransportTrace`                | `{ id, data: TransportTraceEventData }` |\n| `WebRtcIceStateChange`          | `{ id, data: IceState }`                |\n| `WebRtcIceSelectedTupleChange`  | `{ id, data: TransportTuple }`          |\n| `WebRtcDtlsChange`              | `{ id, data: DtlsState }`               |\n| `WebRtcSctpStateChange`         | `{ id, data: SctpState }`               |\n| `PlainTransportTuple`           | `{ id, data: TransportTuple }`          |\n| `PlainTransportRtcpTuple`       | `{ id, data: TransportTuple }`          |\n| `PlainTransportSctpStateChange` | `{ id, data: SctpState }`               |\n| `PipeTransportSctpStateChange`  | `{ id, data: SctpState }`               |\n| `DirectTransportRtcp`           | `{ id, data: Buffer }`                  |\n\n**Consumer Events**\n\n| Event                                              | Payload                                     |\n| -------------------------------------------------- | ------------------------------------------- |\n| `ConsumerCreated`                                  | `{ id }`                                    |\n| `ConsumerClose`                                    | `{ id }`                                    |\n| `ConsumerPause` / `ConsumerResume`                 | `{ id }`                                    |\n| `ConsumerTransportClose`                           | `{ id }`                                    |\n| `ConsumerProducerClose`                            | `{ id }`                                    |\n| `ConsumerProducerPause` / `ConsumerProducerResume` | `{ id }`                                    |\n| `ConsumerScore`                                    | `{ id, data: ConsumerScore }`               |\n| `ConsumerLayersChange`                             | `{ id, data: ConsumerLayers \\| undefined }` |\n| `ConsumerTrace`                                    | `{ id, data: ConsumerTraceEventData }`      |\n| `ConsumerRtp`                                      | `{ id, data: Buffer }`                      |\n\n**Producer Events**\n\n| Event                              | Payload                                  |\n| ---------------------------------- | ---------------------------------------- |\n| `ProducerCreated`                  | `{ id }`                                 |\n| `ProducerClose`                    | `{ id }`                                 |\n| `ProducerPause` / `ProducerResume` | `{ id }`                                 |\n| `ProducerTransportClose`           | `{ id }`                                 |\n| `ProducerScore`                    | `{ id, data: ProducerScore[] }`          |\n| `ProducerTrace`                    | `{ id, data: ProducerTraceEventData }`   |\n| `ProducerVideoOrientationChange`   | `{ id, data: ProducerVideoOrientation }` |\n\n**Data Consumer Events**\n\n| Event                                      | Payload                                           |\n| ------------------------------------------ | ------------------------------------------------- |\n| `DataConsumerCreated`                      | `{ id }`                                          |\n| `DataConsumerClose`                        | `{ id }`                                          |\n| `DataConsumerPause` / `DataConsumerResume` | `{ id }`                                          |\n| `DataConsumerMessage`                      | `{ id, data: { message: Buffer, ppid: number } }` |\n| `DataConsumerSctpSendBufferFull`           | `{ id }`                                          |\n| `DataConsumerBufferedAmountLow`            | `{ id, data: number }`                            |\n\n**Data Producer Events**\n\n| Event                                      | Payload  |\n| ------------------------------------------ | -------- |\n| `DataProducerCreated`                      | `{ id }` |\n| `DataProducerClose`                        | `{ id }` |\n| `DataProducerPause` / `DataProducerResume` | `{ id }` |\n| `DataProducerTransportClose`               | `{ id }` |\n\n**RTP Observer Events**\n\n| Event                                    | Payload                                              |\n| ---------------------------------------- | ---------------------------------------------------- |\n| `RtpObserverCreated`                     | `{ id }`                                             |\n| `RtpObserverClose`                       | `{ id }`                                             |\n| `RtpObserverPause` / `RtpObserverResume` | `{ id }`                                             |\n| `RtpObserverSilence`                     | `{ id }`                                             |\n| `RtpObserverVolumes`                     | `{ id, data: AudioLevelObserverVolume[] }`           |\n| `RtpObserverDominantSpeaker`             | `{ id, data: ActiveSpeakerObserverDominantSpeaker }` |\n\n**WebRTC Server Events**\n\n| Event                            | Payload                         |\n| -------------------------------- | ------------------------------- |\n| `WebRtcServerCreated`            | `{ id }`                        |\n| `WebRtcServerClose`              | `{ id }`                        |\n| `WebRtcServerTransportHandled`   | `{ id, data: WebRtcTransport }` |\n| `WebRtcServerTransportUnhandled` | `{ id, data: WebRtcTransport }` |\n\n## AppData Schemas\n\nThe module attaches structured `appData` to every mediasoup entity for telemetry and routing.\n\n### `WorkerAppData`\n\n```typescript\n{\n  count: {\n    routers: number;\n    transports: number;\n    producers: number;\n    consumers: number;\n    rtpObservers: number;\n    dataProducers: number;\n    dataConsumers: number;\n  }\n  timestamp: number; // Unix ms — when the worker was created\n}\n```\n\n### `RouterAppData`\n\n```typescript\n{\n  workerPid: number;\n  timestamp: number;\n  count: {\n    transports: number;\n    producers: number;\n    consumers: number;\n    rtpObservers: number;\n    dataProducers: number;\n    dataConsumers: number;\n  }\n}\n```\n\n### `TransportAppData`\n\n```typescript\n{\n  routerId: string;\n  timestamp: number;\n  direction?: 'send' | 'recv'; // set automatically on produce/consume\n  connected: boolean;\n  reconnectCount: number;\n  lastConnectedAt?: number;\n  lastDisconnectedAt?: number;\n}\n```\n\n### `ConsumerProducerAppData`\n\n```typescript\n{\n  routerId: string;\n  transportId: string;\n  timestamp: number;\n}\n```\n\n## Architecture\n\n```\nMediasoupModule\n├── MediasoupService       — Public API: create & query all resources\n├── ObserverService        — Internal: hooks into mediasoup native observers,\n│                            updates resource store, emits typed NestJS events\n├── ResourceStoreProvider  — Shared Map-based registry for all entities\n\nEventEmitter2 (global)\n└── All mediasoup events → strongly-typed NestJS events\n    └── @OnMediasoup() decorator for easy subscription\n```\n\n**Lifecycle:**\n\n1. On `onApplicationBootstrap`, the module spawns `workerCount` Workers.\n2. The global `mediasoup.observer` fires `newworker` for each Worker.\n3. `ObserverService.observer()` is called, which registers the Worker in the store, sets up all nested event hooks (Router → Transport → Producer/Consumer → RtpObserver), and starts emitting NestJS events.\n4. On `onApplicationShutdown`, all Workers are closed gracefully.\n\n## Examples\n\n### Full WebRTC SFU Flow\n\n```typescript\n// 1. Create a router\nconst router = await mediasoup.createRouter();\n\n// 2. Create send transport for publisher\nconst sendTransport = await mediasoup.createWebRtcTransport(router.id, {\n  listenIps: [{ ip: '0.0.0.0', announcedIp: process.env.ANNOUNCED_IP }],\n  enableUdp: true,\n  enableTcp: true,\n});\n\n// 3. Create producer (after client calls transport.produce())\nconst producer = await mediasoup.createProducer(sendTransport.id, 'video', clientRtpParameters);\n\n// 4. Create recv transport for subscriber\nconst recvTransport = await mediasoup.createWebRtcTransport(router.id, {\n  listenIps: [{ ip: '0.0.0.0', announcedIp: process.env.ANNOUNCED_IP }],\n  enableUdp: true,\n});\n\n// 5. Create consumer\nconst consumer = await mediasoup.createConsumer(recvTransport.id, producer.id, subscriberRtpCapabilities);\n```\n\n### Active Speaker and Audio Level Detection\n\n```typescript\n@OnMediasoup('RouterCreated')\nasync handleRouterCrated(payload: MediasoupEventData<'RouterCreated'>) {\n await this.mediasoup.createAudioLevelObserver(payload.id);\n await this.mediasoup.createActiveSpeakerObserver(payload.id);\n}\n\n@OnMediasoup('ProducerCreated')\nasync handleProducerCreated(payload: MediasoupEventData<'ProducerCreated'>) {\n const { id, appData } = this.mediasoup.getProducerById(payload.id);\n const router = this.mediasoup.getRouterById(appData.routerId);\n const routerRtp = this.mediasoup.getRtpObserversByRouter(router.id);\n const observers = routerRtp.map((r) => r.addProducer({ producerId: id }));\n\n await Promise.allSettled(observers);\n}\n```\n\n```typescript\n@OnMediasoup('RtpObserverVolumes')\nhandleObserverVolumes(payload: MediasoupEventData<'RtpObserverVolumes'>) {\n // implementation\n}\n```\n\n```typescript\n@OnMediasoup('RtpObserverSilence')\nhandleObserverSilence(payload: MediasoupEventData<'RtpObserverSilence'>) {\n // implementation\n}\n```\n\n```typescript\n@OnMediasoup('RtpObserverDominantSpeaker')\nhandleDominantSpeaker(payload: MediasoupEventData<'RtpObserverDominantSpeaker'>) {\n // implementation\n}\n```\n\n## Contributing\n\nContributions are welcome! Please open an issue or pull request on [GitHub](https://github.com/azversan/mediasoup-module).\n\n## License\n\n[MIT](https://github.com/azversan/mediasoup-module/blob/main/LICENSE)\n","readmeFilename":"README.md"}