Skip to content

Commit

Permalink
Bugfixes (#157)
Browse files Browse the repository at this point in the history
* Several bugfixes and improvements

- Verify disc space on start as well. Recording is not going to start if
  space not enough.
- space_full event occures correctly now
- unsuscribe progress, file_created & space_full events when ffmpeg process stopped only. Not before as it was.
- Event start occurs before progress
  • Loading branch information
boonya committed Oct 31, 2021
1 parent 7454f95 commit 16031ef
Show file tree
Hide file tree
Showing 22 changed files with 384 additions and 221 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project should be documented in this file.

## [2.0.1-alpha.6] - Several bugfixes and improvements

- Verify disc space on "start" as well. Recording is not going to start if space not enough.
- "space_full" event occurs correctly now
- unsubscribe "progress", "file_created" & "space_full" events when ffmpeg process stopped only.
- Event "start" occurs before "progress"

## [2.0.0-alpha.5] - FFMPEG HLS

- Simplified code
Expand Down Expand Up @@ -40,7 +47,7 @@ Nothing really interesting so far.

- `RecorderValidationError` throws an errors list in addition to just a message.


[2.0.1-alpha.6]: https://github.com/boonya/rtsp-video-recorder/compare/2.0.0-alpha.5...2.0.1-alpha.6
[2.0.0-alpha.5]: https://github.com/boonya/rtsp-video-recorder/compare/1.4.0-alpha.4...2.0.0-alpha.5
[1.4.0-alpha.4]: https://github.com/boonya/rtsp-video-recorder/compare/1.4.0-alpha.3...1.4.0-alpha.4
[1.4.0-alpha.3]: https://github.com/boonya/rtsp-video-recorder/compare/1.4.0-alpha.2...1.4.0-alpha.3
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,23 @@ recorder.on(RecorderEvents.START, (payload) => {

#### `stop` event

Normal stop

```ts
recorder.on(RecorderEvents.STOP, (payload) => {
assert.equal(payload, 'programmatically');
});
```

or
If space full

```ts
recorder.on(RecorderEvents.STOP, (payload) => {
assert.equal(payload, 'space_full');
});
```

In case of other errors

```ts
recorder.on(RecorderEvents.STOP, (payload) => {
Expand Down Expand Up @@ -94,19 +104,19 @@ recorder.on(RecorderEvents.STARTED, (payload) => {

#### `stopped` event

If stopped programmatically handler receives 0 exit code & reason message that it stopped programmatically.
If stopped because of space full handler receives 0 exit code & reason message 'space_full'.

```ts
recorder.on(RecorderEvents.STOPPED, (payload) => {
assert.equal(payload, 0, 'Programmatically stopped.');
assert.equal(payload, 0, 'space_full');
});
```

Or if stop reason is FFMPEG process exited, handler receives an exit code of ffmpeg process and a message that FFMPEG exited.

```ts
recorder.on(RecorderEvents.STOPPED, (payload) => {
assert.equal(payload, 255, 'FFMPEG exited. Code 255.');
assert.equal(payload, 255, 'ffmpeg_exited');
});
```

Expand Down
18 changes: 16 additions & 2 deletions example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const log = (event: string) => (...args: unknown[]) => {
console.log();
};

function logProgress(...args: unknown[]) {
return log(RecorderEvents.PROGRESS)(...args);
}

readline.emitKeypressEvents(process.stdin);
if (process.stdin.isTTY) {
process.stdin.setRawMode(true);
Expand Down Expand Up @@ -50,15 +54,25 @@ try {
);

if (SHOW_PROGRESS) {
recorder.on(RecorderEvents.PROGRESS, log(RecorderEvents.PROGRESS));
recorder.on(RecorderEvents.PROGRESS, logProgress);
}
else {
recorder.on(RecorderEvents.PROGRESS, logProgress)
.on(RecorderEvents.STARTED, () => {
recorder.removeListener(RecorderEvents.PROGRESS, logProgress);
})
.on(RecorderEvents.STOP, () => {
recorder.on(RecorderEvents.PROGRESS, logProgress);
});
}

recorder
.on(RecorderEvents.START, log(RecorderEvents.START))
.on(RecorderEvents.STARTED, log(RecorderEvents.STARTED))
.on(RecorderEvents.STOP, log(RecorderEvents.STOP))
.on(RecorderEvents.STOPPED, log(RecorderEvents.STOPPED))
.on(RecorderEvents.ERROR, log(RecorderEvents.ERROR))
.on(RecorderEvents.FILE_CREATED, log(RecorderEvents.FILE_CREATED))
.on(RecorderEvents.STOP, log(RecorderEvents.STOP))
.on(RecorderEvents.SPACE_FULL, log(RecorderEvents.SPACE_FULL))
.start();

Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rtsp-video-recorder",
"version": "2.0.0-alpha.5",
"version": "2.0.1-alpha.6",
"description": "Provide an API to record rtsp video stream to filesystem.",
"main": "dist/recorder.js",
"types": "dist/recorder.d.ts",
Expand Down
116 changes: 0 additions & 116 deletions src/helpers.ts

This file was deleted.

16 changes: 16 additions & 0 deletions src/helpers/directoryExists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import fs from 'fs';

export default function directoryExists(path: string) {
try {
const stats = fs.lstatSync(path);
if (!stats.isDirectory()) {
throw new TypeError(`${path} exists but it is not a directory.`);
}
return true;
} catch (err) {
if (err instanceof TypeError) {
throw err;
}
return false;
}
}
38 changes: 38 additions & 0 deletions src/helpers/segmentTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { DurationFactor, SegmentTimeOption } from '../types';

const SEGMENT_TIME_PATTERN = /^(\d+)(s|m|h)?$/;

export default function transformSegmentTime(value: SegmentTimeOption) {
if (typeof value === 'number') return value;
const [operand, factor] = matchSegmentTime(value);
return getDuration(operand, factor);
}

function matchSegmentTime(value: string): [number, DurationFactor] {
const match = value.match(SEGMENT_TIME_PATTERN);
if (!match) {
throw new Error(`segmentTime value has to match to pattern ${SEGMENT_TIME_PATTERN.toString()}.`);
}
const operand = Number(match[1]);
if (!operand) {
throw new Error('segmentTime value has to be more than zero.');
}

const factor = match[2] as DurationFactor;
return [operand, factor];
}

/**
* @returns seconds
*/
function getDuration(operand: number, factor: DurationFactor): number {
switch (factor) {
case DurationFactor.Minutes:
return operand * 60;
case DurationFactor.Hours:
return operand * Math.pow(60, 2);
case DurationFactor.Seconds:
default:
return operand;
}
}
38 changes: 38 additions & 0 deletions src/helpers/sizeThreshold.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { BytesFactor, DirSizeThresholdOption } from '../types';

const DIR_SIZE_THRESHOLD_PATTERN = /^(\d+)(M|G|T)?$/;

export default function transformDirSizeThreshold(value: DirSizeThresholdOption) {
if (typeof value === 'number') return value;
const [operand, factor] = matchDirSizeThreshold(value);
return getBytesSize(operand, factor);
}

function matchDirSizeThreshold(value: string): [number, BytesFactor] {
const match = value.match(DIR_SIZE_THRESHOLD_PATTERN);
if (!match) {
throw new Error(`dirSizeThreshold value has to match to pattern ${DIR_SIZE_THRESHOLD_PATTERN.toString()}.`);
}
const operand = Number(match[1]);
if (!operand) {
throw new Error('dirSizeThreshold value has to be more than zero.');
}

const factor = match[2] as BytesFactor;
return [operand, factor];
}

/**
* @returns bytes
*/
function getBytesSize(operand: number, factor: BytesFactor): number {
switch (factor) {
case BytesFactor.Gigabytes:
return operand * Math.pow(1024, 3);
case BytesFactor.Terabytes:
return operand * Math.pow(1024, 4);
case BytesFactor.Megabytes:
default:
return operand * Math.pow(1024, 2);
}
}
28 changes: 28 additions & 0 deletions src/helpers/space.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import fs from 'fs';
import pathApi from 'path';

/**
* @returns bytes
*/
export default function dirSize(path: string) {
return getDirListing(path)
.map((item) => fs.statSync(item).size)
.reduce((acc, size) => acc + size, 0);
}

function getDirListing(dir: string): string[] {
return fs.readdirSync(dir)
.map((item) => {
const path = pathApi.join(dir, item);
if (fs.statSync(path).isDirectory()) {
return getDirListing(path);
}
return path;
})
.reduce<string[]>((acc, i) => {
if (Array.isArray(i)) {
return [...acc, ...i];
}
return [...acc, i];
}, []);
}

0 comments on commit 16031ef

Please sign in to comment.