!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 

uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/usr/local/lib/node_modules/homebridge-camera-ui/server/services/   drwxr-xr-x
Free 13.33 GB of 57.97 GB (23%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     ffmpeg.service.js (4.96 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
'use-strict';

const fs = require('fs-extra');
const piexif = require('piexifjs');
const spawn = require('child_process').spawn;

const logger = require('../../services/logger/logger.service.js');
const ping = require('./ping.service');

class Ffmpeg {
  replaceJpegWithExifJPEG(cameraName, filePath, label) {
    let jpeg;

    try {
      jpeg = fs.readFileSync(filePath);
    } catch {
      logger.debug(`Can not read file ${filePath} to create EXIF information, skipping..`);
    }

    if (!jpeg) return;

    const data = jpeg.toString('binary');

    const zeroth = {};

    zeroth[piexif.ImageIFD.XPTitle] = [...Buffer.from(cameraName, 'ucs2')];
    zeroth[piexif.ImageIFD.XPComment] = [...Buffer.from(label, 'ucs2')];
    zeroth[piexif.ImageIFD.XPAuthor] = [...Buffer.from('camera.ui', 'ucs2')];

    const exifObject = { '0th': zeroth, Exif: {}, GPS: {} };
    const exifbytes = piexif.dump(exifObject);

    var newData = piexif.insert(exifbytes, data);
    var newJpeg = Buffer.from(newData, 'binary');

    return fs.writeFileSync(filePath, newJpeg);
  }

  async storeBuffer(cameraName, imageBuffer, name, isPlaceholder, recPath, label) {
    let outputPath = recPath + '/' + name + (isPlaceholder ? '@2' : '') + '.jpeg';
    await fs.outputFile(outputPath, imageBuffer, { encoding: 'base64' });
    this.replaceJpegWithExifJPEG(cameraName, outputPath, label);

    return;
  }

  getAndStoreSnapshot(cameraName, videoConfig, name, additional, recPath, label, store, timeout) {
    return new Promise((resolve, reject) => {
      ping.status(videoConfig, timeout).then((status) => {
        if (status) {
          const videoProcessor = videoConfig.videoProcessor || 'ffmpeg';
          const source = videoConfig.source;
          const width = videoConfig.maxWidth || 1280;
          const height = videoConfig.maxHeight || 720;
          const videoFilter = videoConfig.videoFilter;

          logger.debug(`Snapshot requested: ${width}x${height}`, cameraName, true);

          let ffmpegArguments = source.replace('-i', '-nostdin -y -i');
          let destination = store ? recPath + '/' + name + (additional ? '@2' : '') + '.jpeg' : '-f image2 -';

          ffmpegArguments +=
            ' -hide_banner -loglevel error' +
            ' -frames:v 1' +
            ' -filter:v' +
            ` scale='min(${width},iw)':'min(${height},ih)':force_original_aspect_ratio=decrease,scale=trunc(iw/2)*2:trunc(ih/2)*2` +
            (videoFilter ? `,${videoFilter} ` : ' ') +
            destination;

          const ffmpeg = spawn('ffmpeg', ffmpegArguments.split(/\s+/), { env: process.env });

          let imageBuffer = Buffer.alloc(0);

          logger.debug(`Snapshot command: ${videoProcessor} ${ffmpegArguments}`, cameraName, true);

          ffmpeg.stdout.on('data', (data) => {
            imageBuffer = Buffer.concat([imageBuffer, data]);
          });

          ffmpeg.on('error', (error) => {
            reject(error);
          });

          ffmpeg.on('close', () => {
            if (!imageBuffer || (imageBuffer && imageBuffer.length <= 0)) {
              return reject(new Error('Image Buffer is empty!'));
            }

            if (store) this.replaceJpegWithExifJPEG(cameraName, destination, label);
            resolve(imageBuffer);
          });
        } else {
          reject(new Error('Camera offline'));
        }
      });
    });
  }

  // eslint-disable-next-line no-unused-vars
  storeVideo(cameraName, videoConfig, name, recPath, recTimer, label, timeout) {
    return new Promise((resolve, reject) => {
      ping.status(videoConfig, timeout).then((status) => {
        if (status) {
          const videoProcessor = videoConfig.videoProcessor || 'ffmpeg';
          const source = videoConfig.source;
          const width = videoConfig.maxWidth || 1280;
          const height = videoConfig.maxHeight || 720;
          const videoFilter = videoConfig.videoFilter;

          logger.debug(`Video requested: ${width}x${height}`, cameraName, true);

          let ffmpegArguments = source.replace('-i', '-nostdin -y -i');
          let videoName = recPath + '/' + name + '.mp4';

          ffmpegArguments +=
            ' -hide_banner -loglevel error' +
            ` -t ${recTimer}` +
            (videoFilter ? ' -filter:v ' + videoFilter : '') +
            ' -strict experimental' +
            ' -threads 0' +
            ' -c:v copy' +
            ` -s ${width}x${height}` +
            ' -movflags +faststart' +
            ' -crf 23 ' +
            videoName;

          const ffmpeg = spawn(videoProcessor, ffmpegArguments.split(/\s+/), { env: process.env });

          logger.debug(`Video command: ${videoProcessor} ${ffmpegArguments}`, cameraName, true);

          ffmpeg.on('error', (error) => {
            reject(error);
          });

          ffmpeg.on('close', () => {
            logger.debug(`Video stored to: ${videoName}`);
            resolve();
          });
        } else {
          reject(new Error('Camera offline'));
        }
      });
    });
  }
}

module.exports = new Ffmpeg();

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0056 ]--