Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Camera: Replace ffmpeg-fluent by native commands #2132

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions server/services/rtsp-camera/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const RtspCameraHandler = require('./lib');
const RtspCameraController = require('./api/rtspCamera.controller');

module.exports = function RtspCameraService(gladys, serviceId) {
const ffmpeg = require('fluent-ffmpeg');
const device = new RtspCameraHandler(gladys, ffmpeg, childProcess, serviceId);
const device = new RtspCameraHandler(gladys, childProcess, serviceId);
/**
* @public
* @description This function starts service.
Expand Down
61 changes: 33 additions & 28 deletions server/services/rtsp-camera/lib/getImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,55 +38,60 @@ async function getImage(device) {
this.gladys.config.tempFolder,
`camera-${device.id}-${now.getMilliseconds()}-${now.getSeconds()}-${now.getMinutes()}-${now.getHours()}.jpg`,
);
// we create a writestream
const writeStream = fse.createWriteStream(filePath);
const outputOptions = [
'-vframes 1',
'-qscale:v 15', // Effective range for JPEG is 2-31 with 31 being the worst quality.
];

const args = ['-i', cameraUrlParam.value, '-f', 'image2', '-vframes', '1', '-qscale:v', '15'];

args.push('-vf');
switch (cameraRotationParam.value) {
case DEVICE_ROTATION.DEGREES_90:
outputOptions.push('-vf scale=640:-1,transpose=1'); // Rotate 90
args.push('scale=640:-1,transpose=1'); // Rotate 90
break;
case DEVICE_ROTATION.DEGREES_180:
outputOptions.push('-vf scale=640:-1,transpose=1,transpose=1'); // Rotate 180
args.push('scale=640:-1,transpose=1,transpose=1'); // Rotate 180
break;
case DEVICE_ROTATION.DEGREES_270:
outputOptions.push('-vf scale=640:-1,transpose=2'); // Rotate 270
args.push('scale=640:-1,transpose=2'); // Rotate 270
break;
default:
outputOptions.push('-vf scale=640:-1'); // Rotate 0
args.push('scale=640:-1'); // Rotate 0
break;
}

// Send a camera thumbnail to this stream
// Add a timeout to prevent ffmpeg from running forever
this.ffmpeg(cameraUrlParam.value, { timeout: 10 })
.format('image2')
.outputOptions(outputOptions)
.output(writeStream)
.on('end', async () => {
// add destination file path
args.push(filePath);

logger.debug(`Getting camera image on URL ${cameraUrlParam.value}`);
this.childProcess.execFile(
'ffmpeg',
args,
{
timeout: 10 * 1000, // 10 second max
},
async (error, stdout, stderr) => {
if (error) {
logger.warn(error);
await fse.remove(filePath);
return reject(error);
}
logger.debug('Camera image saved to disk. Reading disk.');
let image;
try {
image = await fse.readFile(filePath);
} catch (e) {
reject(e);
return;
await fse.remove(filePath);
return reject(e);
}
logger.debug('Camera image read from disk, converting to base64');

// convert binary data to base64 encoded string
const cameraImageBase = Buffer.from(image).toString('base64');
const cameraImage = `image/png;base64,${cameraImageBase}`;
const cameraImage = `image/jpg;base64,${cameraImageBase}`;
logger.debug('Camera converted to base64, resolving.');
resolve(cameraImage);
await fse.remove(filePath);
})
.on('error', async (err, stdout, stderr) => {
logger.debug(`Cannot process video: ${err.message}`);
logger.debug(stderr);
reject(err.message);
await fse.remove(filePath);
})
.run();
return null;
},
);
});
}

Expand Down
6 changes: 2 additions & 4 deletions server/services/rtsp-camera/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ const { stopStreaming } = require('./stopStreaming');
/**
* @description Add ability to connect to RTSP camera.
* @param {object} gladys - Gladys instance.
* @param {object} ffmpeg - Ffmpeg library.
* @param {object} childProcess - ChildProcess library.
* @param {string} serviceId - UUID of the service in DB.
* @example
* const rtspCameraHandler = new RtspCameraHandler(gladys, ffmpeg, serviceId);
* const rtspCameraHandler = new RtspCameraHandler(gladys, childProcess, serviceId);
*/
const RtspCameraHandler = function RtspCameraHandler(gladys, ffmpeg, childProcess, serviceId) {
const RtspCameraHandler = function RtspCameraHandler(gladys, childProcess, serviceId) {
this.gladys = gladys;
this.ffmpeg = ffmpeg;
this.childProcess = childProcess;
this.serviceId = serviceId;
this.checkIfLiveActiveFrequencyInSeconds = 10;
Expand Down
61 changes: 0 additions & 61 deletions server/services/rtsp-camera/package-lock.json

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

1 change: 0 additions & 1 deletion server/services/rtsp-camera/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"dependencies": {
"bluebird": "^3.7.2",
"bottleneck": "^2.19.5",
"fluent-ffmpeg": "^2.1.2",
"fs-extra": "^8.0.1"
}
}
33 changes: 0 additions & 33 deletions server/test/services/rtsp-camera/FfmpegMock.test.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const { expect, assert } = require('chai');
const fse = require('fs-extra');
const path = require('path');
const { fake, assert: fakeAssert } = require('sinon');
const FfmpegMock = require('./FfmpegMock.test');
const RtspCameraManager = require('../../../services/rtsp-camera/lib');
const { NotFoundError } = require('../../../utils/coreErrors');

Expand Down Expand Up @@ -41,12 +40,7 @@ describe('Camera.convertLocalStreamToGateway', () => {
const indexFilePath = path.join(folderPath, 'index.m3u8');
const keyfilePath = path.join(folderPath, 'index.m3u8.key');
const videoFilePath = path.join(folderPath, 'index0.ts');
const rtspCameraManager = new RtspCameraManager(
gladys,
FfmpegMock,
childProcessMock,
'de051f90-f34a-4fd5-be2e-e502339ec9bc',
);
const rtspCameraManager = new RtspCameraManager(gladys, childProcessMock, 'de051f90-f34a-4fd5-be2e-e502339ec9bc');
before(async () => {
await fse.ensureDir(folderPath);
await fse.writeFile(indexFilePath, 'this is index');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const { expect } = require('chai');
const fse = require('fs-extra');
const path = require('path');
const { fake, assert: fakeAssert } = require('sinon');
const FfmpegMock = require('./FfmpegMock.test');
const RtspCameraManager = require('../../../services/rtsp-camera/lib');

const device = {
Expand Down Expand Up @@ -51,12 +50,7 @@ describe('Camera.onNewCameraFile', () => {
await fse.remove(folderPath);
});
beforeEach(() => {
rtspCameraManager = new RtspCameraManager(
gladys,
FfmpegMock,
childProcessMock,
'de051f90-f34a-4fd5-be2e-e502339ec9bc',
);
rtspCameraManager = new RtspCameraManager(gladys, childProcessMock, 'de051f90-f34a-4fd5-be2e-e502339ec9bc');
rtspCameraManager.sendCameraFileToGatewayLimited = fake.resolves(null);
});
it('should return directly, no live stream', async () => {
Expand Down Expand Up @@ -111,12 +105,7 @@ describe('Camera.onNewCameraFile', () => {
fakeAssert.calledWith(eventEmitter.emit, 'gateway-ready');
});
it('should upload a file that fail, and return null', async () => {
rtspCameraManager = new RtspCameraManager(
gladys,
FfmpegMock,
childProcessMock,
'de051f90-f34a-4fd5-be2e-e502339ec9bc',
);
rtspCameraManager = new RtspCameraManager(gladys, childProcessMock, 'de051f90-f34a-4fd5-be2e-e502339ec9bc');
rtspCameraManager.sendCameraFileToGatewayLimited = fake.rejects(null);
rtspCameraManager.liveStreams.set('my-camera', {
isGladysGateway: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const fse = require('fs-extra');
const path = require('path');
const { fake, assert: fakeAssert } = require('sinon');
const FfmpegMock = require('./FfmpegMock.test');
const RtspCameraManager = require('../../../services/rtsp-camera/lib');

const gladys = {
Expand All @@ -23,12 +22,7 @@ describe('Camera.sendCameraFileToGateway', () => {
const indexFilePath = path.join(folderPath, 'index.m3u8');
const keyfilePath = path.join(folderPath, 'index.m3u8.key');
const videoFilePath = path.join(folderPath, 'index0.ts');
const rtspCameraManager = new RtspCameraManager(
gladys,
FfmpegMock,
childProcessMock,
'de051f90-f34a-4fd5-be2e-e502339ec9bc',
);
const rtspCameraManager = new RtspCameraManager(gladys, childProcessMock, 'de051f90-f34a-4fd5-be2e-e502339ec9bc');
before(async () => {
await fse.ensureDir(folderPath);
await fse.writeFile(indexFilePath, 'this is index');
Expand Down
Loading
Loading