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

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-163-generic #173-Ubuntu SMP Tue Oct 14 17:51:00 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/note.picotech.app/public_html/src/services/   drwxr-xr-x
Free 25.88 GB of 117.98 GB (21.93%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     ffmpegService.js (5.12 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
const ffmpeg = require('fluent-ffmpeg');
const fs = require('fs').promises;
const path = require('path');
const { AudioChunk } = require('../models');
const { AppError } = require('../middleware/errorHandler');
const { decryptFile, isFileEncrypted } = require('./encryptionService');

const CHUNK_DURATION = 60; // 30 seconds per chunk
const OUTPUT_FORMAT = 'wav';
const OUTPUT_CODEC = 'pcm_s16le';
const SAMPLE_RATE = 16000; // 16kHz for better transcription quality

/**
 * Check if FFmpeg is available
 */
async function checkFFmpeg() {
  return new Promise((resolve, reject) => {
    ffmpeg.getAvailableFormats((err, formats) => {
      if (err) {
        reject(new AppError('FFmpeg is not available: ' + err.message, 500));
      } else {
        resolve(true);
      }
    });
  });
}

/**
 * Get audio duration using FFmpeg
 */
async function getAudioDuration(filePath) {
  return new Promise((resolve, reject) => {
    ffmpeg.ffprobe(filePath, (err, metadata) => {
      if (err) {
        reject(new AppError('Failed to get audio duration: ' + err.message, 500));
      } else {
        const duration = metadata.format.duration * 1000; // Convert to milliseconds
        resolve(Math.floor(duration));
      }
    });
  });
}

/**
 * Create audio chunks from a recording
 */
async function createChunks(recording) {
  try {
    let inputPath = recording.file_path;
    let needsCleanup = false;

    // Check if file is encrypted
    const isEncrypted = await isFileEncrypted(inputPath);
    if (isEncrypted) {
      // Decrypt to temporary location
      const tempDir = path.join(path.dirname(inputPath), 'temp');
      await fs.mkdir(tempDir, { recursive: true });
      const tempPath = path.join(tempDir, `decrypted_${recording.file_name}`);
      await decryptFile(inputPath, tempPath);
      inputPath = tempPath;
      needsCleanup = true;
    }

    const recordingDuration = recording.duration;

    const chunksDir = path.join(path.dirname(recording.file_path), 'chunks');
    await fs.mkdir(chunksDir, { recursive: true });

    const numChunks = Math.ceil(recordingDuration / (CHUNK_DURATION * 1000));
    const chunks = [];

    for (let i = 0; i < numChunks; i++) {
      const startTime = i * CHUNK_DURATION;
      const chunkDuration = Math.min(CHUNK_DURATION, (recordingDuration / 1000) - startTime);

      const chunkFileName = `${path.parse(recording.file_name).name}_chunk_${i}.${OUTPUT_FORMAT}`;
      const chunkFilePath = path.join(chunksDir, chunkFileName);

      // Create chunk using FFmpeg
      await createChunk(inputPath, chunkFilePath, startTime, chunkDuration);

      // Get chunk file size
      const stats = await fs.stat(chunkFilePath);

      // Create AudioChunk record
      const chunk = await AudioChunk.create({
        recording_id: recording.id,
        chunk_index: i,
        file_path: chunkFilePath,
        file_name: chunkFileName,
        start_time: startTime * 1000,
        end_time: (startTime + chunkDuration) * 1000,
        duration: chunkDuration * 1000,
        file_size: stats.size,
        status: 'completed',
      });

      chunks.push(chunk);
    }

    // Clean up temporary decrypted file
    if (needsCleanup) {
      try {
        await fs.unlink(inputPath);
      } catch (error) {
        console.warn('Failed to clean up temporary decrypted file:', error);
      }
    }

    await recording.updateChunkingStatus('completed');
    return chunks;

  } catch (error) {
    await recording.updateChunkingStatus('failed', error.message);
    throw error;
  }
}

/**
 * Create a single audio chunk using FFmpeg
 */
async function createChunk(inputPath, outputPath, startTime, duration) {
  return new Promise((resolve, reject) => {
    ffmpeg(inputPath)
      .setStartTime(startTime)
      .setDuration(duration)
      .audioCodec(OUTPUT_CODEC)
      .audioFrequency(SAMPLE_RATE)
      .audioChannels(1) // Mono for better processing
      .toFormat(OUTPUT_FORMAT)
      .on('end', () => {
        resolve();
      })
      .on('error', (err) => {
        reject(new AppError('FFmpeg chunk creation failed: ' + err.message, 500));
      })
      .save(outputPath);
  });
}

/**
 * Clean up chunks for a recording
 */
async function cleanupChunks(recordingId) {
  try {
    const chunks = await AudioChunk.findByRecording(recordingId);

    for (const chunk of chunks) {
      try {
        await fs.unlink(chunk.file_path);
      } catch (error) {
        console.warn(`Failed to delete chunk file: ${chunk.file_path}`, error);
      }
      await chunk.destroy();
    }
  } catch (error) {
    console.error('Error cleaning up chunks:', error);
  }
}

/**
 * Get chunking progress for a recording
 */
async function getChunkingProgress(recordingId) {
  const totalChunks = await AudioChunk.count({
    where: { recording_id: recordingId }
  });

  const completedChunks = await AudioChunk.count({
    where: {
      recording_id: recordingId,
      status: 'completed'
    }
  });

  return {
    total: totalChunks,
    completed: completedChunks,
    progress: totalChunks > 0 ? (completedChunks / totalChunks) * 100 : 0
  };
}

module.exports = {
  checkFFmpeg,
  getAudioDuration,
  createChunks,
  createChunk,
  cleanupChunks,
  getChunkingProgress,
};

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

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

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