diff --git a/appinfo/info.xml b/appinfo/info.xml
index ce40bd90..6101a3f6 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -43,7 +43,6 @@ Memories is a *batteries-included* photo management solution for Nextcloud with
OCA\Memories\Command\Index
- OCA\Memories\Command\VideoSetup
OCA\Memories\Command\PlacesSetup
OCA\Memories\Command\MigrateGoogleTakeout
diff --git a/lib/Command/VideoSetup.php b/lib/Command/VideoSetup.php
deleted file mode 100644
index b2dd398b..00000000
--- a/lib/Command/VideoSetup.php
+++ /dev/null
@@ -1,469 +0,0 @@
-
- * @author Varun Patil
- * @license AGPL-3.0-or-later
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-namespace OCA\Memories\Command;
-
-use OCP\IConfig;
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-
-class VideoSetup extends Command
-{
- protected IConfig $config;
- protected OutputInterface $output;
- protected string $sampleFile;
- protected string $logFile;
-
- public function __construct(
- IConfig $config
- ) {
- parent::__construct();
- $this->config = $config;
- }
-
- protected function configure(): void
- {
- $this
- ->setName('memories:video-setup')
- ->setDescription('Setup video streaming')
- ->addOption('print-config', null, null, 'Print the current go-vod configuration JSON')
- ;
- }
-
- protected function execute(InputInterface $input, OutputInterface $output): int
- {
- $this->output = $output;
-
- // Check if we just need the config
- if ($input->getOption('print-config')) {
- $conf = \OCA\Memories\Controller\VideoController::getGoVodConfig(\OC::$server->get(IConfig::class));
- $output->writeln(json_encode($conf, JSON_PRETTY_PRINT));
-
- return 0;
- }
-
- // Print some information
- $output->writeln('');
- $output->writeln('This command will help you setup video streaming');
- $output->writeln('It will check if ffmpeg and ffprobe are installed and go-vod (the transcoder) works');
- $output->writeln('If you are running go-vod externally, feature detection will not work properly');
- $output->writeln('In that case you will need to manually adjust the configuration file (add --print-config)');
- $output->writeln('For details on hardware support: https://github.com/pulsejet/memories/wiki/HW-Transcoding');
- $output->writeln('');
- $output->writeln('Press enter to continue or CTRL+C to abort');
- if (false === fgets(STDIN)) {
- return 1;
- }
-
- // Preset executables
- $ffmpegPath = $this->config->getSystemValue('memories.vod.ffmpeg', 'ffmpeg');
- if ('ffmpeg' === $ffmpegPath) {
- $ffmpegPath = trim(shell_exec('which ffmpeg') ?: 'ffmpeg');
- $this->config->setSystemValue('memories.vod.ffmpeg', $ffmpegPath);
- }
- $ffprobePath = $this->config->getSystemValue('memories.vod.ffprobe', 'ffprobe');
- if ('ffprobe' === $ffprobePath) {
- $ffprobePath = trim(shell_exec('which ffprobe') ?: 'ffprobe');
- $this->config->setSystemValue('memories.vod.ffprobe', $ffprobePath);
- }
-
- // Get ffmpeg version
- $ffmpeg = shell_exec("{$ffmpegPath} -version") ?: '';
- if (false === strpos($ffmpeg, 'ffmpeg version')) {
- $ffmpeg = null;
- $output->writeln('ffmpeg is not installed');
- } else {
- $output->writeln('ffmpeg is installed');
- }
-
- // Get ffprobe version
- $ffprobe = shell_exec("{$ffprobePath} -version") ?: '';
- if (false === strpos($ffprobe, 'ffprobe version')) {
- $ffprobe = null;
- $output->writeln('ffprobe is not installed');
- } else {
- $output->writeln('ffprobe is installed');
- }
-
- if (null === $ffmpeg || null === $ffprobe) {
- $output->writeln('ffmpeg and ffprobe are required for video transcoding');
-
- return $this->suggestDisable();
- }
-
- // Check go-vod binary
- $output->writeln('Checking for go-vod binary');
- $goVodPath = $this->config->getSystemValue('memories.vod.path', false);
-
- if (!\is_string($goVodPath) || !file_exists($goVodPath)) {
- // Detect architecture
- $arch = \OCA\Memories\Util::getArch();
- $goVodPath = realpath(__DIR__."/../../exiftool-bin/go-vod-{$arch}");
-
- if (!$goVodPath) {
- $output->writeln('Compatible go-vod binary not found');
- $this->suggestGoVod();
-
- return $this->suggestDisable();
- }
- }
-
- $output->writeln("Trying go-vod from {$goVodPath}");
- chmod($goVodPath, 0755);
-
- $goVod = shell_exec($goVodPath.' test');
- if (!$goVod || false === strpos($goVod, 'test successful')) {
- $output->writeln('go-vod could not be run');
- $this->suggestGoVod();
-
- return $this->suggestDisable();
- }
-
- // Go transcode is working. Yay!
- $output->writeln('go-vod is installed!');
- $output->writeln('');
- $output->writeln('You can use transcoding and HLS streaming');
- $output->writeln('This is recommended for better performance, but has implications if');
- $output->writeln('you are using external storage or run Nextcloud on a slow system.');
- $output->writeln('');
- $output->writeln('Read the following documentation carefully before continuing:');
- $output->writeln('https://github.com/pulsejet/memories/wiki/Configuration');
- $output->writeln('');
- $output->writeln('Do you want to enable transcoding and HLS? [Y/n]');
-
- if ('n' === trim(fgets(fopen('php://stdin', 'r')))) {
- $this->config->setSystemValue('memories.vod.disable', true);
- $output->writeln('Transcoding and HLS are now disabled');
-
- $this->killGoVod($goVodPath);
-
- return 0;
- }
-
- $this->config->setSystemValue('memories.vod.path', $goVodPath);
- $this->config->setSystemValue('memories.vod.disable', false);
-
- // Feature detection
- $this->detectFeatures();
-
- // Success
- $output->writeln("\nTranscoding and HLS are now enabled! Monitor the log file for any errors");
- $output->writeln('You should restart the server for changes to take effect');
-
- $this->killGoVod();
-
- return 0;
- }
-
- protected function suggestGoVod(): void
- {
- $this->output->writeln('You may build go-vod from source');
- $this->output->writeln('It can be downloaded from https://github.com/pulsejet/go-vod');
- $this->output->writeln('Once built, point the path to the binary in the config for `memories.vod.path`');
- }
-
- protected function suggestDisable()
- {
- $this->output->writeln('Without transcoding, video playback may be slow and limited');
- $this->output->writeln('Do you want to disable transcoding and HLS streaming? [y/N]');
- if ('y' !== trim(fgets(fopen('php://stdin', 'r')))) {
- $this->output->writeln('Aborting');
-
- return 1;
- }
-
- $this->config->setSystemValue('memories.vod.disable', true);
- $this->output->writeln('Transcoding and HLS are now disabled');
- $this->output->writeln('You should restart the server for changes to take effect');
-
- return 0;
- }
-
- protected function detectFeatures()
- {
- // Reset the current configuration
- $this->config->deleteSystemValue('memories.vod.vaapi');
- $this->config->deleteSystemValue('memories.vod.nvenc');
-
- $this->output->writeln("\nStarting ffmpeg feature detection");
- $this->output->writeln('This may take a while. Please be patient');
-
- try {
- // Download test file
- $this->output->write("\nDownloading test video file ... ");
- $this->sampleFile = $this->downloadSampleFile();
- if (!file_exists($this->sampleFile)) {
- $this->output->writeln('FAIL');
- $this->output->writeln('Could not download sample file');
- $this->output->writeln('Failed to perform feature detection');
-
- return;
- }
- $this->output->writeln('OK');
-
- // Start go-vod
- if (!$this->startGoVod()) {
- return;
- }
-
- $this->checkCPU();
- $this->checkVAAPI();
-
- // We need to turn off VAAPI before checking NVENC
- $wasVaapi = $this->config->getSystemValue('memories.vod.vaapi', false);
- $this->config->deleteSystemValue('memories.vod.vaapi');
- $this->checkNVENC();
-
- // Restore VAAPI configuration
- if ($wasVaapi) {
- $this->config->setSystemValue('memories.vod.vaapi', true);
- }
- } finally {
- if (file_exists($this->sampleFile)) {
- unlink($this->sampleFile);
- }
- }
-
- $this->output->writeln("\nFeature detection completed");
- }
-
- protected function checkCPU()
- {
- $this->output->writeln('');
- $this->testResult('CPU');
- }
-
- protected function checkVAAPI()
- {
- // Reset current configuration
- $this->config->deleteSystemValue('memories.vod.vaapi');
- $this->config->deleteSystemValue('memories.vod.vaapi.low_power');
-
- // Check for VAAPI
- $this->output->write("\nChecking for VAAPI acceleration (/dev/dri/renderD128) ... ");
- if (!file_exists('/dev/dri/renderD128')) {
- $this->output->writeln('NOT FOUND');
- $this->config->deleteSystemValue('memories.vod.vaapi');
-
- return;
- }
- $this->output->writeln('OK');
-
- // Check permissions
- $this->output->write('Checking for permissions on /dev/dri/renderD128 ... ');
- if (!is_readable('/dev/dri/renderD128')) {
- $this->output->writeln('NO');
- $this->output->writeln('Current user does not have read permissions on /dev/dri/renderD128');
- $this->output->writeln('VAAPI will not work. You may need to add your user to the video/render groups');
- $this->config->deleteSystemValue('memories.vod.vaapi');
-
- return;
- }
- $this->output->writeln('OK');
-
- // Try enabling VAAPI
- $this->config->setSystemValue('memories.vod.vaapi', true);
- $basic = $this->testResult('VAAPI');
-
- // Try with low_power
- $this->config->setSystemValue('memories.vod.vaapi.low_power', true);
- $lowPower = $this->testResult('VAAPI (low_power)');
- if (!$lowPower) {
- $this->config->deleteSystemValue('memories.vod.vaapi.low_power');
- }
-
- // Check if passed any test
- if (!$basic && !$lowPower) {
- $this->config->deleteSystemValue('memories.vod.vaapi');
-
- return;
- }
-
- // Everything is good
- $this->output->write('Do you want to enable VAAPI acceleration? [Y/n] ');
- if ('n' === trim(fgets(fopen('php://stdin', 'r')))) {
- $this->config->setSystemValue('memories.vod.vaapi', false);
- $this->output->writeln('VAAPI is now disabled');
- } else {
- $this->output->writeln("\nVAAPI is now enabled. You may still need to install the Intel Media Driver");
- $this->output->writeln('and ensure proper permissions for /dev/dri/renderD128.');
- $this->output->writeln('See the documentation for more details.');
- $this->config->setSystemValue('memories.vod.vaapi', true);
- }
- }
-
- protected function checkNVENC()
- {
- $this->output->writeln("\nChecking for NVIDIA acceleration with NVENC");
-
- // Reset the current configuration
- $this->config->deleteSystemValue('memories.vod.nvenc.temporal_aq');
- $this->config->deleteSystemValue('memories.vod.nvenc.scale');
-
- // Basic test
- $this->config->setSystemValue('memories.vod.nvenc', true);
-
- // Different scaling methods
- $this->config->setSystemValue('memories.vod.nvenc.scale', 'npp');
- $withScaleNpp = $this->testResult('NVENC (scale_npp)', true);
- $this->config->setSystemValue('memories.vod.nvenc.scale', 'cuda');
- $withScaleCuda = $this->testResult('NVENC (scale_cuda)', true);
-
- if (!$withScaleNpp && !$withScaleCuda) {
- $this->config->deleteSystemValue('memories.vod.nvenc');
- $this->config->deleteSystemValue('memories.vod.nvenc.scale');
- $this->output->writeln('NVENC does not seem to be available');
-
- return;
- }
- if ($withScaleNpp) {
- $this->config->setSystemValue('memories.vod.nvenc.scale', 'npp');
- } elseif ($withScaleCuda) {
- $this->config->setSystemValue('memories.vod.nvenc.scale', 'cuda');
- }
-
- // Try with temporal-aq
- $this->config->setSystemValue('memories.vod.nvenc.temporal_aq', true);
- if (!$this->testResult('NVENC (temporal-aq)', true)) {
- $this->config->deleteSystemValue('memories.vod.nvenc.temporal_aq');
- }
-
- // Good to go
- $this->output->write('Do you want to enable NVENC acceleration? [Y/n] ');
- if ('n' === trim(fgets(fopen('php://stdin', 'r')))) {
- $this->config->setSystemValue('memories.vod.nvenc', false);
- $this->output->writeln('NVENC is now disabled');
- } else {
- $this->output->writeln('NVENC transcoding is now enabled');
- }
- }
-
- protected function test(): void
- {
- $url = \OCA\Memories\Controller\VideoController::getGoVodUrl('test', $this->sampleFile, '360p-000001.ts');
-
- // Make a GET request
- $ch = curl_init($url);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_HEADER, true);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 5);
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
-
- // Check for errors
- if (curl_errno($ch)) {
- throw new \Exception('Curl: '.curl_error($ch));
- }
-
- // Check for 200
- if (200 !== $httpCode) {
- throw new \Exception('HTTP status: '.$httpCode);
- }
-
- // Check response size is greater than 10kb
- if (\strlen($response) < 10240) {
- throw new \Exception('Response size is too small');
- }
- }
-
- private function testResult(string $name, bool $minor = false): bool
- {
- $this->output->write("Testing transcoding with {$name} ... ");
-
- try {
- $this->restartGoVod($this->output);
- $this->test();
- $this->output->writeln('OK');
-
- return true;
- } catch (\Throwable $e) {
- $msg = $e->getMessage();
- $logFile = $this->logFile;
- $this->output->writeln('FAIL');
- if (!$minor) {
- $this->output->writeln("{$name} transcoding failed with error {$msg}");
- $this->output->writeln("Check the log file of go-vod for more details ({$logFile})");
- }
-
- return false;
- }
- }
-
- private function startGoVod(bool $suppress = false): bool
- {
- if (!$suppress) {
- $this->output->write("\nAttempting to start go-vod ... ");
- }
-
- try {
- $this->logFile = $logFile = \OCA\Memories\Controller\VideoController::startGoVod();
- if (!$suppress) {
- $this->output->writeln('OK');
- $this->output->writeln("go-vod logs will be stored at: {$logFile}");
- }
-
- return true;
- } catch (\Exception $e) {
- if (!$suppress) {
- $this->output->writeln('FAIL');
- } else {
- $this->output->writeln('Failed to (re-)start go-vod');
- }
- $this->output->writeln($e->getMessage());
-
- return false;
- }
- }
-
- private function killGoVod(string $path = ''): void
- {
- if ('' === $path) {
- $path = $this->config->getSystemValue('memories.vod.path');
- }
-
- \OCA\Memories\Util::pkill($path);
- }
-
- private function restartGoVod(): void
- {
- $this->killGoVod();
- sleep(1);
- $this->startGoVod(true);
- }
-
- private function downloadSampleFile(): string
- {
- $sampleFile = tempnam(sys_get_temp_dir(), 'sample.mp4');
- $fp = fopen($sampleFile, 'w+');
- $ch = curl_init('https://github.com/pulsejet/memories-assets/raw/main/sample.mp4');
- curl_setopt($ch, CURLOPT_FILE, $fp);
- curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
- curl_exec($ch);
- curl_close($ch);
- fclose($fp);
-
- return $sampleFile;
- }
-}