mirror of
https://github.com/koush/scrypted.git
synced 2026-02-08 08:19:56 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28e1f5ac8a | ||
|
|
bafe73d296 | ||
|
|
f17ce50f17 | ||
|
|
18f5872be1 | ||
|
|
fdccaaa65e | ||
|
|
6a55172924 | ||
|
|
1e41af77fa | ||
|
|
e169a6e02d | ||
|
|
ef55c834af | ||
|
|
3812ad92ac | ||
|
|
0bdb402e7b | ||
|
|
1588ea250b |
78
packages/client/package-lock.json
generated
78
packages/client/package-lock.json
generated
@@ -1,24 +1,20 @@
|
||||
{
|
||||
"name": "@scrypted/client",
|
||||
"version": "1.1.37",
|
||||
"version": "1.1.38",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/client",
|
||||
"version": "1.1.37",
|
||||
"version": "1.1.38",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@scrypted/types": "^0.2.64",
|
||||
"adm-zip": "^0.5.9",
|
||||
"axios": "^0.25.0",
|
||||
"engine.io-client": "^6.2.2",
|
||||
"linkfs": "^2.1.0",
|
||||
"memfs": "^3.4.1",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.4.34",
|
||||
"@types/ip": "^1.1.0",
|
||||
"@types/node": "^17.0.17",
|
||||
"typescript": "^4.7.4"
|
||||
@@ -63,15 +59,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@types/adm-zip": {
|
||||
"version": "0.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
|
||||
"integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ip": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.0.tgz",
|
||||
@@ -87,14 +74,6 @@
|
||||
"integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/adm-zip": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
|
||||
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==",
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||
@@ -177,11 +156,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fs-monkey": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
|
||||
"integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -220,22 +194,6 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/linkfs": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/linkfs/-/linkfs-2.1.0.tgz",
|
||||
"integrity": "sha512-kmsGcmpvjStZ0ATjuHycBujtNnXiZR28BTivEu0gAMDTT7GEyodcK6zSRtu6xsrdorrPZEIN380x7BD7xEYkew=="
|
||||
},
|
||||
"node_modules/memfs": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
|
||||
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
|
||||
"dependencies": {
|
||||
"fs-monkey": "1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@@ -340,15 +298,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"@types/adm-zip": {
|
||||
"version": "0.4.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.34.tgz",
|
||||
"integrity": "sha512-8ToYLLAYhkRfcmmljrKi22gT2pqu7hGMDtORP1emwIEGmgUTZOsaDjzWFzW5N2frcFRz/50CWt4zA1CxJ73pmQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/ip": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.0.tgz",
|
||||
@@ -364,11 +313,6 @@
|
||||
"integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==",
|
||||
"dev": true
|
||||
},
|
||||
"adm-zip": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
|
||||
"integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||
@@ -426,11 +370,6 @@
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
|
||||
},
|
||||
"fs-monkey": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz",
|
||||
"integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -463,19 +402,6 @@
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"linkfs": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/linkfs/-/linkfs-2.1.0.tgz",
|
||||
"integrity": "sha512-kmsGcmpvjStZ0ATjuHycBujtNnXiZR28BTivEu0gAMDTT7GEyodcK6zSRtu6xsrdorrPZEIN380x7BD7xEYkew=="
|
||||
},
|
||||
"memfs": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
|
||||
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
|
||||
"requires": {
|
||||
"fs-monkey": "1.0.3"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/client",
|
||||
"version": "1.1.37",
|
||||
"version": "1.1.38",
|
||||
"description": "",
|
||||
"main": "dist/packages/client/src/index.js",
|
||||
"scripts": {
|
||||
@@ -12,18 +12,14 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.4.34",
|
||||
"@types/ip": "^1.1.0",
|
||||
"@types/node": "^17.0.17",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@scrypted/types": "^0.2.64",
|
||||
"adm-zip": "^0.5.9",
|
||||
"axios": "^0.25.0",
|
||||
"engine.io-client": "^6.2.2",
|
||||
"linkfs": "^2.1.0",
|
||||
"memfs": "^3.4.1",
|
||||
"rimraf": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
4
packages/rpc/package-lock.json
generated
4
packages/rpc/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/rpc",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/rpc",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/rpc",
|
||||
"version": "0.0.6",
|
||||
"version": "0.0.7",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
||||
4
plugins/core/package-lock.json
generated
4
plugins/core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.1.91",
|
||||
"version": "0.1.94",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.1.91",
|
||||
"version": "0.1.94",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/core",
|
||||
"version": "0.1.91",
|
||||
"version": "0.1.94",
|
||||
"description": "Scrypted Core plugin. Provides the UI, websocket, and engine.io APIs.",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -2,14 +2,23 @@
|
||||
<v-btn text color="primary" @click="onClick">Login</v-btn>
|
||||
</template>
|
||||
<script>
|
||||
import RPCInterface from "./RPCInterface.vue";
|
||||
import qs from 'query-string';
|
||||
import RPCInterface from "./RPCInterface.vue";
|
||||
|
||||
export default {
|
||||
mixins: [RPCInterface],
|
||||
methods: {
|
||||
onChange() { },
|
||||
isIFrame() {
|
||||
try {
|
||||
return window.self !== window.top;
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onClick: function () {
|
||||
// https://stackoverflow.com/a/39387533
|
||||
const windowReference = this.isIFrame() ? window.open(undefined, '_blank') : undefined;
|
||||
this.rpc()
|
||||
.getOauthUrl()
|
||||
.then(data => {
|
||||
@@ -22,7 +31,9 @@ export default {
|
||||
u = new URL(redirect_uri);
|
||||
}
|
||||
catch (e) {
|
||||
u = new URL(redirect_uri, window.location.href);
|
||||
const baseURI = new URL(document.baseURI);
|
||||
const scryptedRootURI = new URL('../../../../', baseURI);
|
||||
u = new URL('.' + redirect_uri, scryptedRootURI);
|
||||
u.hostname = 'localhost';
|
||||
}
|
||||
if (u.hostname === 'localhost') {
|
||||
@@ -40,7 +51,10 @@ export default {
|
||||
r: window.location.toString(),
|
||||
});
|
||||
url.search = qs.stringify(querystring);
|
||||
window.location = url.toString();
|
||||
if (windowReference)
|
||||
windowReference.location = url.toString();
|
||||
else
|
||||
window.location = url.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
4
plugins/prebuffer-mixin/package-lock.json
generated
4
plugins/prebuffer-mixin/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/prebuffer-mixin",
|
||||
"version": "0.9.72",
|
||||
"version": "0.9.73",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/prebuffer-mixin",
|
||||
"version": "0.9.72",
|
||||
"version": "0.9.73",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/prebuffer-mixin",
|
||||
"version": "0.9.72",
|
||||
"version": "0.9.73",
|
||||
"description": "Video Stream Rebroadcast, Prebuffer, and Management Plugin for Scrypted.",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RtspServer, Headers } from "@scrypted/common/src/rtsp-server";
|
||||
import net from 'net';
|
||||
import { Headers, RtspServer } from "@scrypted/common/src/rtsp-server";
|
||||
import fs from 'fs';
|
||||
import net from 'net';
|
||||
|
||||
// non standard extension that dumps the rtp payload to a file.
|
||||
export class FileRtspServer extends RtspServer {
|
||||
@@ -8,8 +8,8 @@ export class FileRtspServer extends RtspServer {
|
||||
segmentBytesWritten = 0;
|
||||
writeConsole: Console;
|
||||
|
||||
constructor(client: net.Socket, sdp?: string) {
|
||||
super(client, sdp);
|
||||
constructor(client: net.Socket, sdp?: string, checkRequest?: (method: string, url: string, headers: Headers, rawMessage: string[]) => Promise<boolean>) {
|
||||
super(client, sdp, undefined, checkRequest);
|
||||
|
||||
this.client.on('close', () => {
|
||||
if (this.writeStream)
|
||||
|
||||
@@ -1114,10 +1114,16 @@ class PrebufferSession {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
const client = await listenZeroSingleClient();
|
||||
const hostname = options?.route === 'external' ? '0.0.0.0' : undefined;
|
||||
const client = await listenZeroSingleClient(hostname);
|
||||
const rtspServerPath = '/' + crypto.randomBytes(8).toString('hex');
|
||||
socketPromise = client.clientPromise.then(async (socket) => {
|
||||
sdp = addTrackControls(sdp);
|
||||
server = new FileRtspServer(socket, sdp);
|
||||
server = new FileRtspServer(socket, sdp, async (method, url, headers, rawMessage) => {
|
||||
server.checkRequest = undefined;
|
||||
const u = new URL(url);
|
||||
return u.pathname === rtspServerPath;
|
||||
});
|
||||
server.writeConsole = this.console;
|
||||
if (session.parserSpecific) {
|
||||
const parserSpecific = session.parserSpecific as RtspSessionParserSpecific;
|
||||
@@ -1142,7 +1148,20 @@ class PrebufferSession {
|
||||
interleavePassthrough = session.parserSpecific && serverPortMap.size === 0;
|
||||
return socket;
|
||||
})
|
||||
url = client.url.replace('tcp://', 'rtsp://');
|
||||
url = client.url.replace('tcp://', 'rtsp://') + rtspServerPath;
|
||||
if (hostname) {
|
||||
try {
|
||||
const addresses = await sdk.endpointManager.getLocalAddresses();
|
||||
const [address] = addresses;
|
||||
if (address) {
|
||||
const u = new URL(url);
|
||||
u.hostname = address;
|
||||
url = u.toString();
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const client = await listenZeroSingleClient();
|
||||
@@ -1252,7 +1271,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
const u = new URL(url);
|
||||
|
||||
for (const session of this.sessions.values()) {
|
||||
if (u.pathname.endsWith(session.rtspServerPath)) {
|
||||
if (u.pathname === '/' + session.rtspServerPath) {
|
||||
server.console = session.console;
|
||||
prebufferSession = session;
|
||||
prebufferSession.ensurePrebufferSession();
|
||||
@@ -1260,7 +1279,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
server.sdp = await prebufferSession.sdp;
|
||||
return true;
|
||||
}
|
||||
if (u.pathname.endsWith(session.rtspServerMutedPath)) {
|
||||
if (u.pathname === '/' + session.rtspServerMutedPath) {
|
||||
server.console = session.console;
|
||||
prebufferSession = session;
|
||||
prebufferSession.ensurePrebufferSession();
|
||||
@@ -1326,7 +1345,7 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
}
|
||||
|
||||
async getVideoStream(options?: RequestMediaStreamOptions): Promise<MediaObject> {
|
||||
if (options?.directMediaStream)
|
||||
if (options?.route === 'direct')
|
||||
return this.mixinDevice.getVideoStream(options);
|
||||
|
||||
await this.ensurePrebufferSessions();
|
||||
|
||||
4
plugins/webrtc/package-lock.json
generated
4
plugins/webrtc/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/webrtc",
|
||||
"version": "0.1.33",
|
||||
"version": "0.1.34",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/webrtc",
|
||||
"version": "0.1.33",
|
||||
"version": "0.1.34",
|
||||
"dependencies": {
|
||||
"@scrypted/common": "file:../../common",
|
||||
"@scrypted/sdk": "file:../../sdk",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/webrtc",
|
||||
"version": "0.1.33",
|
||||
"version": "0.1.34",
|
||||
"scripts": {
|
||||
"scrypted-setup-project": "scrypted-setup-project",
|
||||
"prescrypted-setup-project": "scrypted-package-json",
|
||||
|
||||
@@ -419,12 +419,13 @@ export class WebRTCPlugin extends AutoenableMixinProvider implements DeviceCreat
|
||||
}
|
||||
}
|
||||
|
||||
const iceServers = this.storageSettings.values.useTurnServer
|
||||
? [weriftStunServer, weriftTurnServer]
|
||||
: [weriftStunServer];
|
||||
|
||||
return {
|
||||
iceUseIpv6: false,
|
||||
iceServers: [
|
||||
weriftStunServer,
|
||||
weriftTurnServer,
|
||||
],
|
||||
iceServers,
|
||||
...ret,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -530,13 +530,13 @@ class RequestMediaStreamOptions(TypedDict):
|
||||
container: str
|
||||
destination: MediaStreamDestination
|
||||
destinationId: str
|
||||
directMediaStream: bool
|
||||
id: str
|
||||
metadata: Any
|
||||
name: str
|
||||
prebuffer: float
|
||||
prebufferBytes: float
|
||||
refresh: bool
|
||||
route: Any | Any
|
||||
tool: MediaStreamTool
|
||||
video: VideoStreamOptions
|
||||
pass
|
||||
@@ -555,7 +555,6 @@ class RequestRecordingStreamOptions(TypedDict):
|
||||
container: str
|
||||
destination: MediaStreamDestination
|
||||
destinationId: str
|
||||
directMediaStream: bool
|
||||
duration: float
|
||||
id: str
|
||||
loop: bool
|
||||
@@ -565,6 +564,7 @@ class RequestRecordingStreamOptions(TypedDict):
|
||||
prebuffer: float
|
||||
prebufferBytes: float
|
||||
refresh: bool
|
||||
route: Any | Any
|
||||
startTime: float
|
||||
tool: MediaStreamTool
|
||||
video: VideoStreamOptions
|
||||
|
||||
@@ -568,12 +568,13 @@ export type MediaStreamDestination = "local" | "remote" | "medium-resolution" |
|
||||
|
||||
export interface RequestMediaStreamOptions extends MediaStreamOptions {
|
||||
/**
|
||||
* When retrieving media, setting disableMediaProxies=true
|
||||
* will bypass any intermediaries (NVR, rebroadcast) and retrieve
|
||||
* it directly from the source. This is useful in cases when
|
||||
* peer to peer connections are possible and preferred, such as WebRTC.
|
||||
* When retrieving media, setting route directs how the media should be
|
||||
* retrieved and exposed. A direct route will get the stream
|
||||
* as is from the source. This will bypass any intermediaries if possible,
|
||||
* such as an NVR or restreamers.
|
||||
* An external route will request that that provided route is exposed to the local network.
|
||||
*/
|
||||
directMediaStream?: boolean;
|
||||
route?: 'external' | 'direct';
|
||||
|
||||
/**
|
||||
* Specify the stream refresh behavior when this stream is requested.
|
||||
|
||||
4
server/package-lock.json
generated
4
server/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.6.21",
|
||||
"version": "0.6.22",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.6.21",
|
||||
"version": "0.6.22",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/server",
|
||||
"version": "0.6.22",
|
||||
"version": "0.6.23",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@ffmpeg-installer/ffmpeg": "^1.1.0",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { once } from 'events';
|
||||
import net from 'net';
|
||||
|
||||
export async function listenZero(server: net.Server) {
|
||||
server.listen(0);
|
||||
export async function listenZero(server: net.Server, hostname?: string) {
|
||||
server.listen(0, hostname);
|
||||
await once(server, 'listening');
|
||||
return (server.address() as net.AddressInfo).port;
|
||||
}
|
||||
|
||||
export async function listenZeroSingleClient() {
|
||||
export async function listenZeroSingleClient(hostname?: string) {
|
||||
const server = new net.Server();
|
||||
const port = await listenZero(server);
|
||||
const port = await listenZero(server, hostname);
|
||||
|
||||
const clientPromise = new Promise<net.Socket>((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
@@ -24,7 +24,7 @@ export async function listenZeroSingleClient() {
|
||||
});
|
||||
});
|
||||
|
||||
clientPromise.catch(() => {});
|
||||
clientPromise.catch(() => { });
|
||||
|
||||
return {
|
||||
server,
|
||||
|
||||
@@ -10,6 +10,7 @@ function newDeviceProxy(id: string, systemManager: SystemManagerImpl) {
|
||||
}
|
||||
|
||||
class DeviceProxyHandler implements PrimitiveProxyHandler<any>, ScryptedDevice {
|
||||
customProperties: Map<string | number | symbol, any>;
|
||||
device: Promise<ScryptedDevice>;
|
||||
constructor(public id: string, public systemManager: SystemManagerImpl) {
|
||||
}
|
||||
@@ -43,10 +44,34 @@ class DeviceProxyHandler implements PrimitiveProxyHandler<any>, ScryptedDevice {
|
||||
}
|
||||
}
|
||||
|
||||
deleteProperty(target: any, p: string | symbol): boolean {
|
||||
const prop = p.toString();
|
||||
if (Object.keys(ScryptedInterfaceProperty).includes(prop))
|
||||
return false;
|
||||
|
||||
this.customProperties ||= new Map();
|
||||
this.customProperties.set(p, undefined);
|
||||
return true;
|
||||
}
|
||||
|
||||
set(target: any, p: string | symbol, newValue: any, receiver: any): boolean {
|
||||
const prop = p.toString();
|
||||
if (Object.keys(ScryptedInterfaceProperty).includes(prop))
|
||||
return false;
|
||||
|
||||
this.customProperties ||= new Map();
|
||||
this.customProperties.set(p, newValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
get(target: any, p: PropertyKey, receiver: any): any {
|
||||
if (p === 'id')
|
||||
return this.id;
|
||||
|
||||
if (this.customProperties?.has(p))
|
||||
return this.customProperties.get(p);
|
||||
|
||||
const handled = RpcPeer.handleFunctionInvocations(this, target, p, receiver);
|
||||
if (handled)
|
||||
return handled;
|
||||
|
||||
@@ -171,7 +171,7 @@ class RpcProxy implements PrimitiveProxyHandler<any> {
|
||||
// todo: error constructor adds a "cause" variable in Chrome 93, Node v??
|
||||
export class RPCResultError extends Error {
|
||||
constructor(peer: RpcPeer, message: string, public cause?: Error, options?: { name: string, stack: string | undefined }) {
|
||||
super(`${peer.selfName}:${peer.peerName}: ${message}`);
|
||||
super(`${message}\n${peer.selfName}:${peer.peerName}`);
|
||||
|
||||
if (options?.name) {
|
||||
this.name = options?.name;
|
||||
|
||||
@@ -194,6 +194,12 @@ async function start() {
|
||||
// lack of login from cookie auth.
|
||||
|
||||
const checkToken = (token: string) => {
|
||||
if (process.env.SCRYPTED_ADMIN_USERNAME && process.env.SCRYPTED_ADMIN_TOKEN === token) {
|
||||
res.locals.username = process.env.SCRYPTED_ADMIN_USERNAME;
|
||||
res.locals.aclId = process.env.SCRYPTED_ADMIN_TOKEN;
|
||||
return;
|
||||
}
|
||||
|
||||
const [checkHash, ...tokenParts] = token.split('#');
|
||||
const tokenPart = tokenParts?.join('#');
|
||||
if (checkHash && tokenPart) {
|
||||
|
||||
Reference in New Issue
Block a user