koel/app/Values/TranscodeResult.php

56 lines
1.6 KiB
PHP

<?php
namespace App\Values;
use App\Models\Song;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Process;
final class TranscodeResult
{
public function __construct(public readonly string $path, public readonly string $checksum)
{
}
public static function getForSong(Song $song, int $bitRate, ?string $transcodedPath = null): self
{
/** @var self|null $cached */
$cached = Cache::get("transcoded.{$song->id}.$bitRate");
return $cached?->valid() ? $cached : self::createForSong($song, $bitRate, $transcodedPath);
}
private static function createForSong(Song $song, int $bitRate, ?string $transcodedPath = null): self
{
setlocale(LC_CTYPE, 'en_US.UTF-8'); // #1481 special chars might be stripped otherwise
$dir = sys_get_temp_dir() . '/koel-transcodes';
$transcodedPath ??= sprintf('%s/%s.%s.mp3', $dir, $song, $bitRate);
File::ensureDirectoryExists($dir);
Process::timeout(60)->run([
config('koel.streaming.ffmpeg_path'),
'-i',
$song->storage_metadata->getPath(),
'-vn',
'-b:a',
"{$bitRate}k",
'-preset',
'ultrafast',
'-y', // Overwrite output file if it exists
$transcodedPath,
]);
$cached = new self($transcodedPath, md5_file($transcodedPath));
Cache::forever("transcoded.{$song->id}.$bitRate", $cached);
return $cached;
}
private function valid(): bool
{
return File::isReadable($this->path) && $this->checksum === md5_file($this->path);
}
}