Skip to content

Commit

Permalink
chore: update userMediaStream logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Sec-ant committed Jan 18, 2024
1 parent abbc7f2 commit 7129f5d
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 51 deletions.
74 changes: 55 additions & 19 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/// <reference types="user-media-stream/media-track-shims" />
import { initMediaStream } from "user-media-stream";
import { createVideoScanner } from "./src/scanner/videoScanner.js";
import { createUserMediaStream } from "./src/stream/userMediaStream.js";

const videoElement = document.querySelector("video");

if (videoElement) {
const stream = await initMediaStream(videoElement, {
const userMediaStream = createUserMediaStream(videoElement, {
initConstraints(supportedConstraints) {
console.log("supported constraints", supportedConstraints);
return {
Expand All @@ -28,34 +28,24 @@ if (videoElement) {
console.log("audio capabilities", capabilities);
return {};
},
onStart: () => console.log("stream start"),
onStop: () => console.log("stream stop"),
onUpdate: () => console.log("stream update"),
});

const videoTracks = stream.getVideoTracks();
const audioTracks = stream.getAudioTracks();

console.log("video track", videoTracks);
console.log("audio track", audioTracks);

console.log(
"video track settings",
videoTracks.map((videoTrack) => videoTrack.getSettings()),
);
console.log(
"audio track settings",
audioTracks.map((audioTrack) => audioTrack.getSettings()),
);

const videoScanner = createVideoScanner(videoElement, {
minInterval: 0,
readerOptions: {
formats: [],
},
onDetect: console.log,
onScanStart: () => console.log("scan start"),
onScanStop: () => console.log("scan stop"),
onStart: () => console.log("scan start"),
onStop: () => console.log("scan stop"),
onClose: () => console.log("close"),
});

userMediaStream.start();

videoScanner.start();

// await new Promise<void>((resolve) => {
Expand All @@ -64,6 +54,52 @@ if (videoElement) {
// }, 5000);
// });

userMediaStream.setOptions({
videoConstraints: {
advanced: [
{
exposureMode: "manual",
exposureTime: 1000,
},
],
},
});

userMediaStream.setOptions({
videoConstraints: {
advanced: [
{
exposureMode: "manual",
exposureTime: 10,
},
],
},
});

// userMediaStream.setOptions({
// videoConstraints: (capabilities) => {
// const { min, step } = capabilities.exposureTime ?? {};
// if (typeof min === "number" && typeof step === "number") {
// return {
// advanced: [
// {
// exposureMode: "manual",
// exposureTime: min + 3 * step,
// },
// ],
// };
// } else {
// return {};
// }
// },
// });

// await new Promise<void>((resolve) => {
// setTimeout(() => {
// resolve();
// }, 5000);
// });

// videoScanner.stop();

// await new Promise<void>((resolve) => {
Expand Down
14 changes: 10 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@
},
"dependencies": {
"@types/emscripten": "^1.39.10",
"just-compare": "^2.3.0",
"sha1-uint8array": "^0.10.7",
"user-media-stream": "^0.1.0-beta.4",
"user-media-stream": "^0.1.0-rc.1",
"zustand": "^4.4.7"
}
}
Empty file removed src/scanner/userMediaStream.ts
Empty file.
57 changes: 37 additions & 20 deletions src/scanner/videoScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const MIN_SCAN_INTERVAL = 40;
const scanSymbol = Symbol("scan");
const closeSymbol = Symbol("close");

const startActionSymbol = Symbol("start");
const stopActionSymbol = Symbol("stop");
const closeActionSymbol = Symbol("close");

/**
* Options for configuring the VideoScanner.
*/
Expand Down Expand Up @@ -53,11 +57,11 @@ export interface VideoScannerOptions {
/**
* Callback function that is triggered when the scanning process starts.
*/
onScanStart?: () => void;
onStart?: () => void;
/**
* Callback function that is triggered when the scanning process stops.
*/
onScanStop?: () => void;
onStop?: () => void;
/**
* Callback function that is triggered when the scanning process is closed.
*/
Expand Down Expand Up @@ -85,15 +89,15 @@ interface VideoScannerAction {
/**
* Starts the scanning process.
*/
start: () => void;
[startActionSymbol]: () => void;
/**
* Stops the scanning process.
*/
stop: () => void;
[stopActionSymbol]: () => void;
/**
* Closes the scanner and performs cleanup operations.
*/
close: () => void;
[closeActionSymbol]: () => void;
}

/**
Expand All @@ -116,7 +120,19 @@ const defaultVideoScannerOptions: RequiredVideoScannerOptions = {
/**
* Interface combining actions and a method to update options for the VideoScanner.
*/
export interface VideoScanner extends VideoScannerAction {
export interface VideoScanner {
/**
* Starts the scanning process.
*/
start: VideoScannerAction[typeof startActionSymbol];
/**
* Stops the scanning process.
*/
stop: VideoScannerAction[typeof stopActionSymbol];
/**
* Closes the scanner and performs cleanup operations.
*/
close: VideoScannerAction[typeof closeActionSymbol];
/**
* Update the configuration options of the VideoScanner.
*
Expand Down Expand Up @@ -144,8 +160,8 @@ export function createVideoScanner(
minInterval = defaultVideoScannerOptions.minInterval,
onDetect = defaultVideoScannerOptions.onDetect,
onUpdate = defaultVideoScannerOptions.onUpdate,
onScanStart = defaultVideoScannerOptions.onScanStart,
onScanStop = defaultVideoScannerOptions.onScanStop,
onStart: onStart = defaultVideoScannerOptions.onStart,
onStop: onStop = defaultVideoScannerOptions.onStop,
onClose = defaultVideoScannerOptions.onClose,
}: VideoScannerOptions = defaultVideoScannerOptions,
): VideoScanner {
Expand All @@ -163,21 +179,22 @@ export function createVideoScanner(
wasmLocation,
readerOptions,
minInterval,

onDetect,
onUpdate,
onScanStart,
onScanStop,
onStart,
onStop,
onClose,

start: () => {
[startActionSymbol]: () => {
set({ [scanSymbol]: true });
},

stop: () => {
[stopActionSymbol]: () => {
set({ [scanSymbol]: false });
},

close: () => {
[closeActionSymbol]: () => {
set({ [closeSymbol]: true });
},
})),
Expand All @@ -189,9 +206,9 @@ export function createVideoScanner(
(options) => options[scanSymbol],
(scan) => {
if (scan) {
videoScannerStore.getState().onScanStart?.();
videoScannerStore.getState().onStart?.();
} else {
videoScannerStore.getState().onScanStop?.();
videoScannerStore.getState().onStop?.();
}
},
);
Expand All @@ -203,7 +220,7 @@ export function createVideoScanner(
(close) => {
if (close) {
globalThis.cancelAnimationFrame(requestAnimationFrameId);
videoScannerStore.getState().stop();
videoScannerStore.getState()[stopActionSymbol]();
unsubScan();
unsubClose();
unsubWasmLocation();
Expand Down Expand Up @@ -326,10 +343,10 @@ export function createVideoScanner(
globalThis.requestAnimationFrame(frameRequestCallback);

return {
start: videoScannerStore.getState().start,
stop: videoScannerStore.getState().stop,
close: videoScannerStore.getState().close,
setOptions: (videoScannerOptions: VideoScannerOptions) =>
start: videoScannerStore.getState()[startActionSymbol],
stop: videoScannerStore.getState()[stopActionSymbol],
close: videoScannerStore.getState()[closeActionSymbol],
setOptions: (videoScannerOptions) =>
videoScannerStore.setState(videoScannerOptions),
} as VideoScanner;
}
Expand Down
1 change: 1 addition & 0 deletions src/stream/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./userMediaStream";
25 changes: 22 additions & 3 deletions src/scanner/queuefy.ts → src/stream/queuefy.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// TODO: rewrite

import compare from "just-compare";

/**
* Represent a record of a function invocation, storing the function and its arguments.
*
Expand Down Expand Up @@ -25,6 +29,7 @@ interface QueuefyOptions {
curr: InvokeRecord<I>,
prev: InvokeRecord,
) => boolean;
cleanUp?: () => Promise<unknown>;
}

/**
Expand All @@ -42,9 +47,13 @@ interface CreateQueuefyOptions extends QueuefyOptions {
/**
* Default options for the createQueuefy function, including fail-fast behavior.
*/
const defaultCreateQueuefyOptions: Required<CreateQueuefyOptions> = {
const defaultCreateQueuefyOptions: Required<
Omit<CreateQueuefyOptions, "cleanUp">
> &
CreateQueuefyOptions = {
failFast: true,
skipStrategy: (curr, prev) => Object.is(curr.f, prev.f),
skipStrategy: (curr, prev) =>
Object.is(curr.f, prev.f) && compare(curr.args, prev.args),
};

/**
Expand All @@ -58,6 +67,7 @@ const defaultCreateQueuefyOptions: Required<CreateQueuefyOptions> = {
export function createQueuefy({
failFast = defaultCreateQueuefyOptions.failFast,
skipStrategy: _skipStrategy = defaultCreateQueuefyOptions.skipStrategy,
cleanUp: _cleanUp = defaultCreateQueuefyOptions.cleanUp,
}: CreateQueuefyOptions = {}) {
return (() => {
// Internal queue to manage the execution order.
Expand All @@ -79,14 +89,23 @@ export function createQueuefy({
*/
return <I extends unknown[], O>(
f: (...args: I) => Promise<O>,
{ skipStrategy = _skipStrategy }: QueuefyOptions = {},
{
skipStrategy = _skipStrategy,
cleanUp = _cleanUp,
}: QueuefyOptions = {},
) =>
(...args: I) => {
const currInvokeRecord: InvokeRecord<I> = { f, args };
if (skipStrategy(currInvokeRecord, prevInvokeRecord)) {
return queue as Promise<O>;
}
prevInvokeRecord = currInvokeRecord as unknown as InvokeRecord;
if (cleanUp) {
queue = queue.then(
() => cleanUp(),
failFast ? undefined : () => cleanUp(),
);
}
// Enqueue the function execution, ensuring sequential execution. If `failFast` is true, any
// error will halt the queue. Otherwise, the queue continues despite errors.
return (queue = queue.then(
Expand Down
Loading

0 comments on commit 7129f5d

Please sign in to comment.