support single-frame capture
This commit is contained in:
@@ -27,6 +27,7 @@ Connect to the device's access point (e.g., FTYC811847AGFDZ) and run `node dist/
|
||||
|
||||
## Running
|
||||
|
||||
### HTTP Server
|
||||
To execute the HTTP server, run `node dist/bin.cjs http_server`; you can access the JPEG stream at http://localhost:5000/.
|
||||
|
||||
The roundtrip delay when using MJPEG is [~350ms](pics/delay.jpg?raw=true).
|
||||
@@ -38,9 +39,9 @@ There's a basic UI which can display multiple cameras:
|
||||
Clicking on the image will take you to a page that has audio streaming. Click the button below the image to mute/unmute the audio.
|
||||
|
||||
|
||||
## Settings
|
||||
#### Settings
|
||||
|
||||
You can provide a config file in `yml` format, check `config.example.yml` for an updated example:
|
||||
You can provide a config file in `yml` format, then pass it as an argument: `node bin.cjs http_server --config_file <your_config.yml>`
|
||||
|
||||
```yml
|
||||
http_server:
|
||||
@@ -82,6 +83,12 @@ All keys are optional
|
||||
|
||||
You must restart the HTTP server for changes to the settings file to take effect.
|
||||
|
||||
### Single capture mode
|
||||
|
||||
```bash
|
||||
node bin.cjs frame --discovery_ip 192.168.40.104 --out out.jpg
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## Protocol
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import fs from "node:fs";
|
||||
import { DevSerial } from "./impl.js";
|
||||
import { RemoteInfo } from "dgram";
|
||||
import { logger } from "./logger.js";
|
||||
import { startVideoStream } from "./session.js";
|
||||
import { discoverDevices } from "./discovery.js";
|
||||
import { Session } from "./session.js";
|
||||
import { Handlers, makeSession } from "./session.js";
|
||||
import { config } from "./settings.js";
|
||||
|
||||
const sessions: Record<string, Session> = {};
|
||||
export const captureSingle = ({ discovery_ip, out_file }: { discovery_ip: string; out_file: string }) => {
|
||||
let devEv = discoverDevices([discovery_ip]);
|
||||
|
||||
const startSession = (s: Session) => {
|
||||
startVideoStream(s);
|
||||
logger.info(`Camera ${s.devName} is now ready to stream`);
|
||||
};
|
||||
|
||||
devEv.on("discover", (rinfo: RemoteInfo, dev: DevSerial) => {
|
||||
if (dev.devId in sessions) {
|
||||
logger.info(`Camera ${dev.devId} at ${rinfo.address} already discovered, ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Discovered camera ${dev.devId} at ${rinfo.address}`);
|
||||
const s = makeSession(Handlers, dev, rinfo, startSession, 5000);
|
||||
sessions[dev.devId] = s;
|
||||
config.cameras[dev.devId] = { fix_packet_loss: false };
|
||||
|
||||
s.eventEmitter.on("frame", () => {
|
||||
const assembled = Buffer.concat(s.curImage);
|
||||
fs.writeFileSync(out_file, assembled);
|
||||
logger.info(`Got frame. Exiting`);
|
||||
devEv.emit("close");
|
||||
s.close();
|
||||
});
|
||||
});
|
||||
};
|
||||
+20
@@ -2,6 +2,7 @@ import process from "node:process";
|
||||
import { hideBin } from "yargs/helpers";
|
||||
import yargs from "yargs/yargs";
|
||||
|
||||
import { captureSingle } from "../capture_single.js";
|
||||
import { serveHttp } from "../http_server.js";
|
||||
import { pair } from "../pair.js";
|
||||
import { loadConfig, config } from "../settings.js";
|
||||
@@ -70,5 +71,24 @@ yargs(hideBin(process.argv))
|
||||
pair({ ssid: argv.ssid, password: argv.password });
|
||||
},
|
||||
)
|
||||
.command(
|
||||
"frame",
|
||||
"capture a single frame from the first discovered camera",
|
||||
(yargs) => {
|
||||
return yargs
|
||||
.option("log_level", { describe: "Set log level", default: "info" })
|
||||
.option("discovery_ip", { describe: "Camera discovery IP address", default: "192.168.1.255" })
|
||||
.option("out", { describe: "Path for output file" })
|
||||
.demandOption(["out"])
|
||||
.string(["out", "discovery_ip"]);
|
||||
},
|
||||
(argv) => {
|
||||
buildLogger(argv.log_level, undefined);
|
||||
if (majorVersion < 16) {
|
||||
logger.error(`Node version ${majorVersion} is not supported, may malfunction`);
|
||||
}
|
||||
captureSingle({ discovery_ip: argv.discovery_ip, out_file: argv.out });
|
||||
},
|
||||
)
|
||||
.demandCommand()
|
||||
.parseSync();
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ const deal_with_data = (session: Session, dv: DataView) => {
|
||||
}
|
||||
// this should always be enabled but currently it seems to cause more
|
||||
// visual distortion than just missing some frames
|
||||
if (!config.cameras[session.devName].fix_packet_loss) {
|
||||
if (!config.cameras[session.devName]?.fix_packet_loss) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user