mirror of
https://github.com/koush/scrypted.git
synced 2026-02-16 19:52:15 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd3e7fe238 | ||
|
|
b02c17e185 | ||
|
|
6dee9b04df | ||
|
|
378fb41908 | ||
|
|
48f7208d55 | ||
|
|
71a93805ef | ||
|
|
4880c18c48 | ||
|
|
198d4808cb | ||
|
|
ef8f4ba9b8 | ||
|
|
d87d9bb751 |
817
plugins/prebuffer-mixin/package-lock.json
generated
817
plugins/prebuffer-mixin/package-lock.json
generated
@@ -1,22 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "@scrypted/prebuffer-mixin",
|
"name": "@scrypted/prebuffer-mixin",
|
||||||
"version": "0.10.57",
|
"version": "0.10.58",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@scrypted/prebuffer-mixin",
|
"name": "@scrypted/prebuffer-mixin",
|
||||||
"version": "0.10.57",
|
"version": "0.10.58",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scrypted/common": "file:../../common",
|
"@scrypted/common": "file:../../common",
|
||||||
|
"@scrypted/libav": "^1.0.199",
|
||||||
"@scrypted/sdk": "file:../../sdk",
|
"@scrypted/sdk": "file:../../sdk",
|
||||||
"h264-sps-parser": "^0.2.1",
|
"h264-sps-parser": "^0.2.1",
|
||||||
"semver": "^7.3.7"
|
"semver": "^7.3.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.13.14",
|
||||||
"@types/semver": "^7.3.12"
|
"@types/semver": "^7.3.12",
|
||||||
|
"prebuild-install": "npm:@scrypted/prebuild-install@^7.1.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../common": {
|
"../../common": {
|
||||||
@@ -78,10 +80,34 @@
|
|||||||
"../sdk": {
|
"../sdk": {
|
||||||
"extraneous": true
|
"extraneous": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@isaacs/fs-minipass": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^7.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@scrypted/common": {
|
"node_modules/@scrypted/common": {
|
||||||
"resolved": "../../common",
|
"resolved": "../../common",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@scrypted/libav": {
|
||||||
|
"version": "1.0.199",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scrypted/libav/-/libav-1.0.199.tgz",
|
||||||
|
"integrity": "sha512-sIrTRwa5CSZgnbCzPEB/laBNJ6RoZ3BKkVrgMCX/GE7oYCBcxIYtgFq942DVckXA6+A6NfXBR1lLt8a52SPpyQ==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^2.0.3",
|
||||||
|
"follow-redirects": "^1.15.9",
|
||||||
|
"node-addon-api": "^8.3.1",
|
||||||
|
"tar": "^7.4.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@scrypted/sdk": {
|
"node_modules/@scrypted/sdk": {
|
||||||
"resolved": "../../sdk",
|
"resolved": "../../sdk",
|
||||||
"link": true
|
"link": true
|
||||||
@@ -102,11 +128,369 @@
|
|||||||
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
|
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chownr": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/deep-extend": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/detect-libc": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/expand-template": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(MIT OR WTFPL)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||||
|
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs-constants": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/github-from-package": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/h264-sps-parser": {
|
"node_modules/h264-sps-parser": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/h264-sps-parser/-/h264-sps-parser-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/h264-sps-parser/-/h264-sps-parser-0.2.1.tgz",
|
||||||
"integrity": "sha512-1OCliBfrgCe2fu6eRRqN0xvhp9tFH/UVa1zdVmX/WcQAZrEB6xm/2RJ13F4h2OtQUMJqWv31fZakmTgrvbyIDA=="
|
"integrity": "sha512-1OCliBfrgCe2fu6eRRqN0xvhp9tFH/UVa1zdVmX/WcQAZrEB6xm/2RJ13F4h2OtQUMJqWv31fZakmTgrvbyIDA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/ini": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minizlib": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "dist/cjs/src/bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp-classic": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/napi-build-utils": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/node-abi": {
|
||||||
|
"version": "3.74.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
|
||||||
|
"integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.3.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-addon-api": {
|
||||||
|
"version": "8.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
|
||||||
|
"integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^18 || ^20 || >= 21"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/prebuild-install": {
|
||||||
|
"name": "@scrypted/prebuild-install",
|
||||||
|
"version": "7.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scrypted/prebuild-install/-/prebuild-install-7.1.9.tgz",
|
||||||
|
"integrity": "sha512-lKKX7TMlwToQIH2UX8p0JwFbp0Y2dwedEqgkpcTmRvaA9DOfhau7m40i4+Qo7F1ISMHo/NK1XntURrFlSm4ibg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"detect-libc": "^2.0.0",
|
||||||
|
"expand-template": "^2.0.3",
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"github-from-package": "0.0.0",
|
||||||
|
"minimist": "^1.2.3",
|
||||||
|
"mkdirp-classic": "^0.5.3",
|
||||||
|
"napi-build-utils": "^1.0.1",
|
||||||
|
"node-abi": "^3.3.0",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"rc": "^1.2.7",
|
||||||
|
"tar-fs": "^2.0.0",
|
||||||
|
"tunnel-agent": "^0.6.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"prebuild-install": "bin.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pump": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rc": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||||
|
"dependencies": {
|
||||||
|
"deep-extend": "^0.6.0",
|
||||||
|
"ini": "~1.3.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"strip-json-comments": "~2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"rc": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.1",
|
"version": "7.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
@@ -119,15 +503,133 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-json-comments": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tar": {
|
||||||
|
"version": "7.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||||
|
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/fs-minipass": "^4.0.0",
|
||||||
|
"chownr": "^3.0.0",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"minizlib": "^3.0.1",
|
||||||
|
"mkdirp": "^3.0.1",
|
||||||
|
"yallist": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tar-fs": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chownr": "^1.1.1",
|
||||||
|
"mkdirp-classic": "^0.5.2",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"tar-stream": "^2.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tar-fs/node_modules/chownr": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/tar-stream": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^4.0.3",
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"fs-constants": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tunnel-agent": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "6.20.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@isaacs/fs-minipass": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^7.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@scrypted/common": {
|
"@scrypted/common": {
|
||||||
"version": "file:../../common",
|
"version": "file:../../common",
|
||||||
"requires": {
|
"requires": {
|
||||||
@@ -139,6 +641,17 @@
|
|||||||
"typescript": "^5.5.3"
|
"typescript": "^5.5.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@scrypted/libav": {
|
||||||
|
"version": "1.0.199",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scrypted/libav/-/libav-1.0.199.tgz",
|
||||||
|
"integrity": "sha512-sIrTRwa5CSZgnbCzPEB/laBNJ6RoZ3BKkVrgMCX/GE7oYCBcxIYtgFq942DVckXA6+A6NfXBR1lLt8a52SPpyQ==",
|
||||||
|
"requires": {
|
||||||
|
"detect-libc": "^2.0.3",
|
||||||
|
"follow-redirects": "^1.15.9",
|
||||||
|
"node-addon-api": "^8.3.1",
|
||||||
|
"tar": "^7.4.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@scrypted/sdk": {
|
"@scrypted/sdk": {
|
||||||
"version": "file:../../sdk",
|
"version": "file:../../sdk",
|
||||||
"requires": {
|
"requires": {
|
||||||
@@ -182,21 +695,319 @@
|
|||||||
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
|
"integrity": "sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chownr": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="
|
||||||
|
},
|
||||||
|
"deep-extend": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"detect-libc": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="
|
||||||
|
},
|
||||||
|
"end-of-stream": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"expand-template": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"follow-redirects": {
|
||||||
|
"version": "1.15.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||||
|
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
|
||||||
|
},
|
||||||
|
"fs-constants": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"github-from-package": {
|
||||||
|
"version": "0.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||||
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"h264-sps-parser": {
|
"h264-sps-parser": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/h264-sps-parser/-/h264-sps-parser-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/h264-sps-parser/-/h264-sps-parser-0.2.1.tgz",
|
||||||
"integrity": "sha512-1OCliBfrgCe2fu6eRRqN0xvhp9tFH/UVa1zdVmX/WcQAZrEB6xm/2RJ13F4h2OtQUMJqWv31fZakmTgrvbyIDA=="
|
"integrity": "sha512-1OCliBfrgCe2fu6eRRqN0xvhp9tFH/UVa1zdVmX/WcQAZrEB6xm/2RJ13F4h2OtQUMJqWv31fZakmTgrvbyIDA=="
|
||||||
},
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ini": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="
|
||||||
|
},
|
||||||
|
"minizlib": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="
|
||||||
|
},
|
||||||
|
"mkdirp-classic": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"napi-build-utils": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node-abi": {
|
||||||
|
"version": "3.74.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
|
||||||
|
"integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"semver": "^7.3.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-addon-api": {
|
||||||
|
"version": "8.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
|
||||||
|
"integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA=="
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"prebuild-install": {
|
||||||
|
"version": "npm:@scrypted/prebuild-install@7.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scrypted/prebuild-install/-/prebuild-install-7.1.9.tgz",
|
||||||
|
"integrity": "sha512-lKKX7TMlwToQIH2UX8p0JwFbp0Y2dwedEqgkpcTmRvaA9DOfhau7m40i4+Qo7F1ISMHo/NK1XntURrFlSm4ibg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"detect-libc": "^2.0.0",
|
||||||
|
"expand-template": "^2.0.3",
|
||||||
|
"follow-redirects": "^1.15.6",
|
||||||
|
"github-from-package": "0.0.0",
|
||||||
|
"minimist": "^1.2.3",
|
||||||
|
"mkdirp-classic": "^0.5.3",
|
||||||
|
"napi-build-utils": "^1.0.1",
|
||||||
|
"node-abi": "^3.3.0",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"rc": "^1.2.7",
|
||||||
|
"tar-fs": "^2.0.0",
|
||||||
|
"tunnel-agent": "^0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pump": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rc": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"deep-extend": "^0.6.0",
|
||||||
|
"ini": "~1.3.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"strip-json-comments": "~2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.7.1",
|
"version": "7.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="
|
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-json-comments": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"tar": {
|
||||||
|
"version": "7.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||||
|
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||||
|
"requires": {
|
||||||
|
"@isaacs/fs-minipass": "^4.0.0",
|
||||||
|
"chownr": "^3.0.0",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"minizlib": "^3.0.1",
|
||||||
|
"mkdirp": "^3.0.1",
|
||||||
|
"yallist": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tar-fs": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chownr": "^1.1.1",
|
||||||
|
"mkdirp-classic": "^0.5.2",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"tar-stream": "^2.1.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chownr": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tar-stream": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"bl": "^4.0.3",
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"fs-constants": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tunnel-agent": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"undici-types": {
|
"undici-types": {
|
||||||
"version": "6.20.0",
|
"version": "6.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
|
||||||
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
"integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@scrypted/prebuffer-mixin",
|
"name": "@scrypted/prebuffer-mixin",
|
||||||
"version": "0.10.57",
|
"version": "0.10.58",
|
||||||
"description": "Video Stream Rebroadcast, Prebuffer, and Management Plugin for Scrypted.",
|
"description": "Video Stream Rebroadcast, Prebuffer, and Management Plugin for Scrypted.",
|
||||||
"author": "Scrypted",
|
"author": "Scrypted",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -38,12 +38,14 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scrypted/common": "file:../../common",
|
"@scrypted/common": "file:../../common",
|
||||||
|
"@scrypted/libav": "^1.0.199",
|
||||||
"@scrypted/sdk": "file:../../sdk",
|
"@scrypted/sdk": "file:../../sdk",
|
||||||
"h264-sps-parser": "^0.2.1",
|
"h264-sps-parser": "^0.2.1",
|
||||||
"semver": "^7.3.7"
|
"semver": "^7.3.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.14",
|
"@types/node": "^22.13.14",
|
||||||
"@types/semver": "^7.3.12"
|
"@types/semver": "^7.3.12",
|
||||||
|
"prebuild-install": "npm:@scrypted/prebuild-install@^7.1.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
206
plugins/prebuffer-mixin/src/libav-parser.ts
Normal file
206
plugins/prebuffer-mixin/src/libav-parser.ts
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
import { Deferred } from "@scrypted/common/src/deferred";
|
||||||
|
import { parseSdp } from "@scrypted/common/src/sdp-utils";
|
||||||
|
import { sleep } from "@scrypted/common/src/sleep";
|
||||||
|
import { StreamChunk } from "@scrypted/common/src/stream-parser";
|
||||||
|
import { AVFormatContext, createAVFormatContext } from '@scrypted/libav';
|
||||||
|
import { ResponseMediaStreamOptions } from "@scrypted/sdk";
|
||||||
|
import { once } from 'events';
|
||||||
|
import net from 'net';
|
||||||
|
import { EventEmitter } from "stream";
|
||||||
|
import tls from 'tls';
|
||||||
|
import { RTSP_FRAME_MAGIC } from "../../../common/src/rtsp-server";
|
||||||
|
import { ParserSession, setupActivityTimer } from "./ffmpeg-session";
|
||||||
|
import { installLibavAddon } from "./libav-setup";
|
||||||
|
import { negotiateMediaStream } from "./rfc4571";
|
||||||
|
|
||||||
|
let installPromise: Promise<void>;
|
||||||
|
|
||||||
|
export async function startLibavSession(console: Console, url: string, mediaStreamOptions: ResponseMediaStreamOptions, options: {
|
||||||
|
useUdp: boolean,
|
||||||
|
audioSoftMuted: boolean,
|
||||||
|
activityTimeout: number,
|
||||||
|
}): Promise<ParserSession<"rtsp">> {
|
||||||
|
installPromise ||= installLibavAddon();
|
||||||
|
await installPromise;
|
||||||
|
|
||||||
|
const formatContext = createAVFormatContext();
|
||||||
|
try {
|
||||||
|
return await startLibavSessionWrapped(formatContext, console, url, mediaStreamOptions, options);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
await formatContext.close();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startLibavSessionWrapped(formatContext: AVFormatContext, console: Console, url: string, mediaStreamOptions: ResponseMediaStreamOptions, options: {
|
||||||
|
useUdp: boolean,
|
||||||
|
audioSoftMuted: boolean,
|
||||||
|
activityTimeout: number,
|
||||||
|
}): Promise<ParserSession<"rtsp">> {
|
||||||
|
const events = new EventEmitter();
|
||||||
|
|
||||||
|
let tlsProxy: net.Server;
|
||||||
|
try {
|
||||||
|
if (url.startsWith('rtsps:') || url.startsWith('https:')) {
|
||||||
|
let { hostname, port } = new URL(url);
|
||||||
|
if (!port) {
|
||||||
|
if (url.startsWith('rtsps:'))
|
||||||
|
port = '322';
|
||||||
|
else
|
||||||
|
port = '443';
|
||||||
|
}
|
||||||
|
|
||||||
|
const portNumber = parseInt(port);
|
||||||
|
if (!portNumber)
|
||||||
|
throw new Error('invalid port number');
|
||||||
|
|
||||||
|
tlsProxy = net.createServer(async socket => {
|
||||||
|
try {
|
||||||
|
const tlsSocket = tls.connect({
|
||||||
|
host: hostname,
|
||||||
|
port: portNumber,
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
});
|
||||||
|
await once(tlsSocket, 'secureConnect');
|
||||||
|
socket.pipe(tlsSocket).pipe(socket);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error('tls proxy error', e);
|
||||||
|
socket.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tlsProxy.listen(0, '127.0.0.1');
|
||||||
|
await once(tlsProxy, 'listening');
|
||||||
|
const localPort = (tlsProxy.address() as net.AddressInfo).port;
|
||||||
|
// rewrite the url to use the local port
|
||||||
|
const u = new URL(url);
|
||||||
|
u.protocol = u.protocol.replace('s:', ':');
|
||||||
|
u.hostname = '127.0.0.1';
|
||||||
|
u.port = localPort.toString();
|
||||||
|
url = u.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
await formatContext.open(url, {
|
||||||
|
rtsp_transport: options.useUdp ? 'udp' : 'tcp',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
tlsProxy?.close();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sdp = formatContext.createSDP();
|
||||||
|
const parsedSdp = parseSdp(sdp);
|
||||||
|
// sdp may contain multiple audio/video sections. take only the first video section.
|
||||||
|
sdp = [...parsedSdp.header.lines, ...parsedSdp.msections.map(msection => msection.lines).flat()].join('\r\n');
|
||||||
|
|
||||||
|
const killDeferred = new Deferred<void>();
|
||||||
|
const startDeferred = new Deferred<void>();
|
||||||
|
killDeferred.promise.catch(e => {
|
||||||
|
events.emit('killed');
|
||||||
|
events.emit('error', e);
|
||||||
|
tlsProxy?.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
const kill = (e?: Error) => {
|
||||||
|
killDeferred.reject(e || new Error('killed'));
|
||||||
|
startDeferred.reject(e || new Error('killed'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { resetActivityTimer } = setupActivityTimer('rtsp', kill, events, options?.activityTimeout);
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const pipelines: {
|
||||||
|
streamIndex: number,
|
||||||
|
writeFormatContext: AVFormatContext,
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
await startDeferred.promise;
|
||||||
|
formatContext.streams.forEach(stream => {
|
||||||
|
if (options.audioSoftMuted && stream.type === 'audio')
|
||||||
|
return;
|
||||||
|
if (stream.type !== 'video' && stream.type !== 'audio')
|
||||||
|
return;
|
||||||
|
|
||||||
|
const { codec } = stream;
|
||||||
|
const rtp = createAVFormatContext();
|
||||||
|
rtp.create('rtp', rtp => {
|
||||||
|
const prefix = Buffer.alloc(4);
|
||||||
|
prefix.writeUInt8(RTSP_FRAME_MAGIC, 0);
|
||||||
|
prefix.writeUInt8(stream.index, 1);
|
||||||
|
prefix.writeUInt16BE(rtp.length, 2);
|
||||||
|
|
||||||
|
const chunk: StreamChunk = {
|
||||||
|
chunks: [prefix, rtp],
|
||||||
|
type: codec === 'hevc' ? 'h265' : codec,
|
||||||
|
};
|
||||||
|
|
||||||
|
events.emit('rtsp', chunk);
|
||||||
|
});
|
||||||
|
rtp.newStream({
|
||||||
|
formatContext,
|
||||||
|
streamIndex: stream.index,
|
||||||
|
});
|
||||||
|
|
||||||
|
pipelines.push({
|
||||||
|
streamIndex: stream.index,
|
||||||
|
writeFormatContext: rtp,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
while (!killDeferred.finished) {
|
||||||
|
using result = await formatContext.receiveFrame(pipelines);
|
||||||
|
if (result)
|
||||||
|
resetActivityTimer();
|
||||||
|
if (killDeferred.finished)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
kill(e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
kill(new Error('rtsp read loop exited'));
|
||||||
|
|
||||||
|
await sleep(1000);
|
||||||
|
await Promise.allSettled(pipelines.map(pipeline => pipeline.writeFormatContext.close()));
|
||||||
|
await sleep(1000);
|
||||||
|
await formatContext.close();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: () => {
|
||||||
|
startDeferred.resolve();
|
||||||
|
},
|
||||||
|
sdp: Promise.resolve(sdp),
|
||||||
|
get isActive() { return !killDeferred.finished },
|
||||||
|
kill(error?: Error) {
|
||||||
|
kill(error);
|
||||||
|
},
|
||||||
|
killed: killDeferred.promise,
|
||||||
|
resetActivityTimer,
|
||||||
|
negotiateMediaStream: (requestMediaStream, inputVideoCodec, inputAudioCodec) => {
|
||||||
|
return negotiateMediaStream(sdp, mediaStreamOptions, inputVideoCodec, inputAudioCodec, requestMediaStream);
|
||||||
|
},
|
||||||
|
emit(container: 'rtsp', chunk: StreamChunk) {
|
||||||
|
events.emit(container, chunk);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
on(event: string, cb: any) {
|
||||||
|
events.on(event, cb);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
once(event: any, cb: any) {
|
||||||
|
events.once(event, cb);
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
removeListener(event, cb) {
|
||||||
|
events.removeListener(event, cb);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
plugins/prebuffer-mixin/src/libav-setup.ts
Normal file
19
plugins/prebuffer-mixin/src/libav-setup.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import * as libav from '@scrypted/libav';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
function getAddonInstallPath() {
|
||||||
|
if (process.versions.electron)
|
||||||
|
process.env.npm_config_runtime = 'electron';
|
||||||
|
const binaryUrl = libav.getBinaryUrl();
|
||||||
|
const u = new URL(binaryUrl);
|
||||||
|
const withoutExtension = path.basename(u.pathname).replace(/\.tar.gz$/, '');
|
||||||
|
return path.join(process.env.SCRYPTED_PLUGIN_VOLUME, libav.version, withoutExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function installLibavAddon(installOnly = false) {
|
||||||
|
const nr = installOnly
|
||||||
|
? null
|
||||||
|
// @ts-expect-error
|
||||||
|
: __non_webpack_require__;
|
||||||
|
await libav.install(getAddonInstallPath(), nr);
|
||||||
|
}
|
||||||
@@ -14,8 +14,9 @@ import { parse as h264SpsParse } from "h264-sps-parser";
|
|||||||
import net, { AddressInfo } from 'net';
|
import net, { AddressInfo } from 'net';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Duplex } from 'stream';
|
import { Duplex } from 'stream';
|
||||||
import { ParserOptions, ParserSession, startParserSession } from './ffmpeg-rebroadcast';
|
import { ParserOptions, ParserSession, startParserSession } from './ffmpeg-session';
|
||||||
import { FileRtspServer } from './file-rtsp-server';
|
import { FileRtspServer } from './file-rtsp-server';
|
||||||
|
import { startLibavSession } from './libav-parser';
|
||||||
import { getUrlLocalAdresses } from './local-addresses';
|
import { getUrlLocalAdresses } from './local-addresses';
|
||||||
import { REBROADCAST_MIXIN_INTERFACE_TOKEN } from './rebroadcast-mixin-token';
|
import { REBROADCAST_MIXIN_INTERFACE_TOKEN } from './rebroadcast-mixin-token';
|
||||||
import { connectRFC4571Parser, startRFC4571Parser } from './rfc4571';
|
import { connectRFC4571Parser, startRFC4571Parser } from './rfc4571';
|
||||||
@@ -32,6 +33,8 @@ const SCRYPTED_PARSER_TCP = 'Scrypted (TCP)';
|
|||||||
const SCRYPTED_PARSER_UDP = 'Scrypted (UDP)';
|
const SCRYPTED_PARSER_UDP = 'Scrypted (UDP)';
|
||||||
const FFMPEG_PARSER_TCP = 'FFmpeg (TCP)';
|
const FFMPEG_PARSER_TCP = 'FFmpeg (TCP)';
|
||||||
const FFMPEG_PARSER_UDP = 'FFmpeg (UDP)';
|
const FFMPEG_PARSER_UDP = 'FFmpeg (UDP)';
|
||||||
|
const LIBAV_PARSER_TCP = 'Scrypted libav (TCP)';
|
||||||
|
const LIBAV_PARSER_UDP = 'Scrypted libav (UDP)';
|
||||||
const STRING_DEFAULT = 'Default';
|
const STRING_DEFAULT = 'Default';
|
||||||
|
|
||||||
interface PrebufferStreamChunk extends StreamChunk {
|
interface PrebufferStreamChunk extends StreamChunk {
|
||||||
@@ -59,7 +62,6 @@ class PrebufferSession {
|
|||||||
rtspPrebuffer: PrebufferStreamChunk[] = []
|
rtspPrebuffer: PrebufferStreamChunk[] = []
|
||||||
parsers: { [container: string]: StreamParser };
|
parsers: { [container: string]: StreamParser };
|
||||||
sdp: Promise<string>;
|
sdp: Promise<string>;
|
||||||
usingScryptedParser = false;
|
|
||||||
usingScryptedUdpParser = false;
|
usingScryptedUdpParser = false;
|
||||||
|
|
||||||
mixinDevice: VideoCamera;
|
mixinDevice: VideoCamera;
|
||||||
@@ -236,6 +238,8 @@ class PrebufferSession {
|
|||||||
rtspParser = localStorage.getItem('defaultRtspParser');
|
rtspParser = localStorage.getItem('defaultRtspParser');
|
||||||
}
|
}
|
||||||
switch (rtspParser) {
|
switch (rtspParser) {
|
||||||
|
case LIBAV_PARSER_TCP:
|
||||||
|
case LIBAV_PARSER_UDP:
|
||||||
case FFMPEG_PARSER_TCP:
|
case FFMPEG_PARSER_TCP:
|
||||||
case FFMPEG_PARSER_UDP:
|
case FFMPEG_PARSER_UDP:
|
||||||
case SCRYPTED_PARSER_TCP:
|
case SCRYPTED_PARSER_TCP:
|
||||||
@@ -392,6 +396,8 @@ class PrebufferSession {
|
|||||||
SCRYPTED_PARSER_UDP,
|
SCRYPTED_PARSER_UDP,
|
||||||
FFMPEG_PARSER_TCP,
|
FFMPEG_PARSER_TCP,
|
||||||
FFMPEG_PARSER_UDP,
|
FFMPEG_PARSER_UDP,
|
||||||
|
LIBAV_PARSER_TCP,
|
||||||
|
LIBAV_PARSER_UDP,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -542,12 +548,11 @@ class PrebufferSession {
|
|||||||
// before launching the parser session, clear out the last detected codec.
|
// before launching the parser session, clear out the last detected codec.
|
||||||
// an erroneous cached codec could cause ffmpeg to fail to start.
|
// an erroneous cached codec could cause ffmpeg to fail to start.
|
||||||
this.storage.removeItem(this.lastDetectedAudioCodecKey);
|
this.storage.removeItem(this.lastDetectedAudioCodecKey);
|
||||||
this.usingScryptedParser = false;
|
let usingScryptedParser = false;
|
||||||
|
|
||||||
const h264Oddities = this.getLastH264Oddities();
|
const h264Oddities = this.getLastH264Oddities();
|
||||||
|
|
||||||
if (isRfc4571) {
|
if (isRfc4571) {
|
||||||
this.usingScryptedParser = true;
|
usingScryptedParser = true;
|
||||||
this.console.log('bypassing ffmpeg: using scrypted rfc4571 parser')
|
this.console.log('bypassing ffmpeg: using scrypted rfc4571 parser')
|
||||||
const json = await mediaManager.convertMediaObjectToJSON<any>(mo, 'x-scrypted/x-rfc4571');
|
const json = await mediaManager.convertMediaObjectToJSON<any>(mo, 'x-scrypted/x-rfc4571');
|
||||||
let { url, sdp, mediaStreamOptions } = json;
|
let { url, sdp, mediaStreamOptions } = json;
|
||||||
@@ -566,21 +571,22 @@ class PrebufferSession {
|
|||||||
sessionMso = ffmpegInput.mediaStreamOptions || this.advertisedMediaStreamOptions;
|
sessionMso = ffmpegInput.mediaStreamOptions || this.advertisedMediaStreamOptions;
|
||||||
|
|
||||||
let { parser, isDefault } = this.getParser(sessionMso);
|
let { parser, isDefault } = this.getParser(sessionMso);
|
||||||
this.usingScryptedParser = parser === SCRYPTED_PARSER_TCP || parser === SCRYPTED_PARSER_UDP;
|
usingScryptedParser = parser === SCRYPTED_PARSER_TCP || parser === SCRYPTED_PARSER_UDP;
|
||||||
|
const usingLibavParser = parser === LIBAV_PARSER_TCP || parser === LIBAV_PARSER_UDP;
|
||||||
this.usingScryptedUdpParser = parser === SCRYPTED_PARSER_UDP;
|
this.usingScryptedUdpParser = parser === SCRYPTED_PARSER_UDP;
|
||||||
|
|
||||||
// prefer ffmpeg if this is a prebuffered stream.
|
// prefer ffmpeg if this is a prebuffered stream.
|
||||||
if (isDefault
|
if (isDefault
|
||||||
&& this.usingScryptedParser
|
&& usingScryptedParser
|
||||||
&& h264Oddities
|
&& h264Oddities
|
||||||
&& !this.stopInactive
|
&& !this.stopInactive
|
||||||
&& sessionMso.tool !== 'scrypted') {
|
&& sessionMso.tool !== 'scrypted') {
|
||||||
this.console.warn('H264 oddities were detected in prebuffered video stream, the Default Scrypted RTSP Parser will not be used. Falling back to FFmpeg. This can be overriden by setting the RTSP Parser to Scrypted.');
|
this.console.warn('H264 oddities were detected in prebuffered video stream, the Default Scrypted RTSP Parser will not be used. Falling back to FFmpeg. This can be overriden by setting the RTSP Parser to Scrypted.');
|
||||||
this.usingScryptedParser = false;
|
usingScryptedParser = false;
|
||||||
parser = FFMPEG_PARSER_TCP;
|
parser = FFMPEG_PARSER_TCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.usingScryptedParser) {
|
if (usingScryptedParser) {
|
||||||
const rtspParser = createRtspParser();
|
const rtspParser = createRtspParser();
|
||||||
rbo.parsers.rtsp = rtspParser;
|
rbo.parsers.rtsp = rtspParser;
|
||||||
|
|
||||||
@@ -590,6 +596,16 @@ class PrebufferSession {
|
|||||||
rtspRequestTimeout: 10000,
|
rtspRequestTimeout: 10000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (usingLibavParser) {
|
||||||
|
const rtspParser = createRtspParser();
|
||||||
|
rbo.parsers.rtsp = rtspParser;
|
||||||
|
|
||||||
|
session = await startLibavSession(this.console, ffmpegInput.url, ffmpegInput.mediaStreamOptions, {
|
||||||
|
useUdp: parser === LIBAV_PARSER_UDP,
|
||||||
|
audioSoftMuted,
|
||||||
|
activityTimeout: 10000,
|
||||||
|
});
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
let acodec: string[];
|
let acodec: string[];
|
||||||
|
|
||||||
@@ -646,7 +662,7 @@ class PrebufferSession {
|
|||||||
console.error('rebroadcast error', e)
|
console.error('rebroadcast error', e)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.usingScryptedParser && !isRfc4571) {
|
if (usingScryptedParser && !isRfc4571) {
|
||||||
// watch the stream for 10 seconds to see if an weird nalu is encountered.
|
// watch the stream for 10 seconds to see if an weird nalu is encountered.
|
||||||
// if one is found and using scrypted parser as default, will need to restart rebroadcast to prevent
|
// if one is found and using scrypted parser as default, will need to restart rebroadcast to prevent
|
||||||
// downstream issues.
|
// downstream issues.
|
||||||
@@ -1006,10 +1022,6 @@ class PrebufferSession {
|
|||||||
const codecInfo = await this.parseCodecs(true);
|
const codecInfo = await this.parseCodecs(true);
|
||||||
const mediaStreamOptions: ResponseMediaStreamOptions = session.negotiateMediaStream(options, codecInfo.inputVideoCodec, codecInfo.inputAudioCodec);
|
const mediaStreamOptions: ResponseMediaStreamOptions = session.negotiateMediaStream(options, codecInfo.inputVideoCodec, codecInfo.inputAudioCodec);
|
||||||
let sdp = await this.sdp;
|
let sdp = await this.sdp;
|
||||||
if (!mediaStreamOptions.video?.h264Info && this.usingScryptedParser) {
|
|
||||||
mediaStreamOptions.video ||= {};
|
|
||||||
mediaStreamOptions.video.h264Info = this.getLastH264Probe();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.mixin.streamSettings.storageSettings.values.noAudio)
|
if (this.mixin.streamSettings.storageSettings.values.noAudio)
|
||||||
mediaStreamOptions.audio = null;
|
mediaStreamOptions.audio = null;
|
||||||
@@ -1623,6 +1635,8 @@ export class RebroadcastPlugin extends AutoenableMixinProvider implements MixinP
|
|||||||
SCRYPTED_PARSER_UDP,
|
SCRYPTED_PARSER_UDP,
|
||||||
FFMPEG_PARSER_TCP,
|
FFMPEG_PARSER_TCP,
|
||||||
FFMPEG_PARSER_UDP,
|
FFMPEG_PARSER_UDP,
|
||||||
|
LIBAV_PARSER_TCP,
|
||||||
|
LIBAV_PARSER_UDP,
|
||||||
],
|
],
|
||||||
onPut: () => {
|
onPut: () => {
|
||||||
this.log.a('Rebroadcast Plugin will restart momentarily.');
|
this.log.a('Rebroadcast Plugin will restart momentarily.');
|
||||||
@@ -1755,7 +1769,9 @@ export class RebroadcastPlugin extends AutoenableMixinProvider implements MixinP
|
|||||||
this.setHasEnabledMixin(mixinDeviceState.id);
|
this.setHasEnabledMixin(mixinDeviceState.id);
|
||||||
|
|
||||||
const { id } = mixinDeviceState;
|
const { id } = mixinDeviceState;
|
||||||
const forked = sdk.fork<RebroadcastPluginFork>();
|
const forked = sdk.fork<RebroadcastPluginFork>({
|
||||||
|
runtime: 'node',
|
||||||
|
});
|
||||||
const { worker } = forked;
|
const { worker } = forked;
|
||||||
const result = await forked.result;
|
const result = await forked.result;
|
||||||
const mixin = await result.newPrebufferMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState);
|
const mixin = await result.newPrebufferMixin(mixinDevice, mixinDeviceInterfaces, mixinDeviceState);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { MediaStreamOptions, ResponseMediaStreamOptions } from "@scrypted/sdk";
|
|||||||
import { parse as spsParse } from "h264-sps-parser";
|
import { parse as spsParse } from "h264-sps-parser";
|
||||||
import net from 'net';
|
import net from 'net';
|
||||||
import { EventEmitter, Readable } from "stream";
|
import { EventEmitter, Readable } from "stream";
|
||||||
import { ParserSession, setupActivityTimer } from "./ffmpeg-rebroadcast";
|
import { ParserSession, setupActivityTimer } from "./ffmpeg-session";
|
||||||
import { getSpsResolution } from "./sps-resolution";
|
import { getSpsResolution } from "./sps-resolution";
|
||||||
|
|
||||||
export function negotiateMediaStream(sdp: string, mediaStreamOptions: MediaStreamOptions, inputVideoCodec: string, inputAudioCodec: string, requestMediaStream: MediaStreamOptions) {
|
export function negotiateMediaStream(sdp: string, mediaStreamOptions: MediaStreamOptions, inputVideoCodec: string, inputAudioCodec: string, requestMediaStream: MediaStreamOptions) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { StreamChunk } from "@scrypted/common/src/stream-parser";
|
|||||||
import { ResponseMediaStreamOptions } from "@scrypted/sdk";
|
import { ResponseMediaStreamOptions } from "@scrypted/sdk";
|
||||||
import dgram from 'dgram';
|
import dgram from 'dgram';
|
||||||
import { EventEmitter } from "stream";
|
import { EventEmitter } from "stream";
|
||||||
import { ParserSession, setupActivityTimer } from "./ffmpeg-rebroadcast";
|
import { ParserSession, setupActivityTimer } from "./ffmpeg-session";
|
||||||
import { negotiateMediaStream } from "./rfc4571";
|
import { negotiateMediaStream } from "./rfc4571";
|
||||||
|
|
||||||
export type RtspChannelCodecMapping = { [key: number]: string };
|
export type RtspChannelCodecMapping = { [key: number]: string };
|
||||||
|
|||||||
Reference in New Issue
Block a user