#4050 -- Make each live DJ recording create a broadcast, not the other way around.

This commit is contained in:
Buster "Silver Eagle" Neece 2022-04-18 04:22:54 -05:00
parent 3d53b111f8
commit 617f06e278
No known key found for this signature in database
GPG Key ID: 9FC8B9E008872109
6 changed files with 89 additions and 65 deletions

View File

@ -6,6 +6,7 @@ namespace App\Entity\Repository;
use App\Doctrine\Repository;
use App\Entity;
use Carbon\CarbonImmutable;
/**
* @extends Repository<Entity\StationStreamerBroadcast>
@ -65,8 +66,63 @@ class StationStreamerBroadcastRepository extends Repository
public function findByPath(Entity\Station $station, string $path): ?Entity\StationStreamerBroadcast
{
return $this->repository->findOneBy([
'station' => $station,
'station' => $station,
'recordingPath' => $path,
]);
}
public function getOrCreateFromPath(
Entity\Station $station,
string $recordingPath,
): ?Entity\StationStreamerBroadcast {
$streamerUsername = pathinfo($recordingPath, PATHINFO_DIRNAME);
$streamer = $this->em->getRepository(Entity\StationStreamer::class)
->findOneBy([
'station' => $station,
'streamer_username' => $streamerUsername,
'is_active' => 1,
]);
if (null === $streamer) {
return null;
}
$startTimeRaw = str_replace(
Entity\StationStreamerBroadcast::PATH_PREFIX . '_',
'',
pathinfo($recordingPath, PATHINFO_FILENAME)
);
$startTime = CarbonImmutable::createFromFormat(
'Ymd-His',
$startTimeRaw,
$station->getTimezoneObject()
);
if (false === $startTime) {
return null;
}
$record = $this->em->createQuery(
<<<'DQL'
SELECT ssb
FROM App\Entity\StationStreamerBroadcast ssb
WHERE ssb.streamer = :streamer
AND ssb.timestampStart >= :start AND ssb.timestampStart <= :end
AND ssb.recordingPath IS NULL
DQL
)->setParameter('streamer', $streamer)
->setParameter('start', $startTime->subMinute()->getTimestamp())
->setParameter('end', $startTime->addMinute()->getTimestamp())
->setMaxResults(1)
->getOneOrNullResult();
if (null === $record) {
$record = new Entity\StationStreamerBroadcast($streamer);
}
$record->setTimestampStart($startTime->getTimestamp());
$record->setRecordingPath($recordingPath);
return $record;
}
}

View File

@ -9,7 +9,6 @@ use App\Doctrine\Repository;
use App\Entity;
use App\Environment;
use App\Radio\AutoDJ\Scheduler;
use App\Radio\Enums\StreamFormats;
use Psr\Log\LoggerInterface;
use Symfony\Component\Serializer\Serializer;
@ -82,21 +81,8 @@ class StationStreamerRepository extends Repository
$record = new Entity\StationStreamerBroadcast($streamer);
$this->em->persist($record);
$backendConfig = $station->getBackendConfig();
$recordStreams = $backendConfig->recordStreams();
if ($recordStreams) {
$format = $backendConfig->getRecordStreamsFormatEnum() ?? StreamFormats::Mp3;
$recordingPath = $record->generateRecordingPath($format);
$this->em->persist($record);
$this->em->flush();
return $recordingPath;
}
$this->em->flush();
return true;
}
@ -115,7 +101,7 @@ class StationStreamerRepository extends Repository
return true;
}
protected function getStreamer(Entity\Station $station, string $username = ''): ?Entity\StationStreamer
public function getStreamer(Entity\Station $station, string $username = ''): ?Entity\StationStreamer
{
/** @var Entity\StationStreamer|null $streamer */
$streamer = $this->repository->findOneBy(

View File

@ -5,8 +5,6 @@ declare(strict_types=1);
namespace App\Entity;
use App\Entity\Interfaces\IdentifiableEntityInterface;
use App\Radio\Enums\StreamFormats;
use Carbon\CarbonImmutable;
use Doctrine\ORM\Mapping as ORM;
use OpenApi\Attributes as OA;
@ -69,6 +67,11 @@ class StationStreamerBroadcast implements IdentifiableEntityInterface
return $this->timestampStart;
}
public function setTimestampStart(int $timestampStart): void
{
$this->timestampStart = $timestampStart;
}
public function getTimestampEnd(): int
{
return $this->timestampEnd;
@ -84,17 +87,9 @@ class StationStreamerBroadcast implements IdentifiableEntityInterface
return $this->recordingPath;
}
public function generateRecordingPath(StreamFormats $format): string
public function setRecordingPath(?string $recordingPath): void
{
$now = CarbonImmutable::createFromTimestamp(
$this->timestampStart,
$this->station->getTimezoneObject()
);
$this->recordingPath = $this->streamer->getStreamerUsername()
. '/' . self::PATH_PREFIX . '_' . $now->format('Ymd-His') . '.' . $format->getExtension();
return $this->recordingPath;
$this->recordingPath = $recordingPath;
}
public function clearRecordingPath(): void

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace App\Radio\Backend\Liquidsoap\Command;
use App\Entity;
use App\Flysystem\StationFilesystems;
use Monolog\Logger;
class DjOnCommand extends AbstractCommand
@ -31,14 +30,6 @@ class DjOnCommand extends AbstractCommand
]
);
$resp = $this->streamerRepo->onConnect($station, $user);
if (is_string($resp)) {
return (new StationFilesystems($station))
->getTempFilesystem()
->getLocalPath($resp);
}
return $resp;
return $this->streamerRepo->onConnect($station, $user);
}
}

View File

@ -714,8 +714,6 @@ class ConfigWriter implements EventSubscriberInterface
last_authenticated_dj = ref("")
live_dj = ref("")
live_record_path = ref("")
def dj_auth(login) =
auth_info =
if (login.user == "source" or login.user == "") and (string.match(pattern="(:|,)+", login.password)) then
@ -747,36 +745,22 @@ class ConfigWriter implements EventSubscriberInterface
live_enabled := true
live_dj := dj
j = json()
j.add("user", dj)
response = azuracast_api_call(
_ = azuracast_api_call(
timeout=5,
"djon",
json.stringify(j)
json.stringify({user = dj})
)
if string.contains(prefix="/", response) then
live_record_path := response
end
end
def live_disconnected() =
dj = !live_dj
j = json()
j.add("user", dj)
_ = azuracast_api_call(
timeout=5,
"djoff",
json.stringify(j)
json.stringify({user = !live_dj})
)
live_enabled := false
last_authenticated_dj := ""
live_dj := ""
live_record_path := ""
end
EOF
);
@ -828,16 +812,21 @@ class ConfigWriter implements EventSubscriberInterface
$recordLiveStreamsBitrate = (int)($settings['record_streams_bitrate'] ?? 128);
$formatString = $this->getOutputFormatString($recordLiveStreamsFormat, $recordLiveStreamsBitrate);
$recordExtension = $recordLiveStreamsFormat->getExtension();
$recordBasePath = self::cleanUpString($station->getRadioTempDir());
$recordPathPrefix = Entity\StationStreamerBroadcast::PATH_PREFIX;
$event->appendBlock(
<<< EOF
# Record Live Broadcasts
recording_base_path = "${recordBasePath}"
recording_extension = "${recordExtension}"
output.file(
{$formatString},
fun () -> begin
path = !live_record_path
if (path != "") then
"#{path}.tmp"
if (!live_enabled) then
"#{recording_base_path}/#{!live_dj}/${recordPathPrefix}_%Y%m%d-%H%M%S.#{recording_extension}.tmp"
else
""
end

View File

@ -76,14 +76,21 @@ class MoveBroadcastsTask extends AbstractTask
. 'Check temporary directory at path to recover file.',
[
'storageLocation' => (string)$storageLocation,
'path' => $recordingPath,
'path' => $recordingPath,
]
);
break;
}
$broadcast = $this->broadcastRepo->findByPath($station, $recordingPath);
$broadcast = $this->broadcastRepo->getOrCreateFromPath($station, $recordingPath);
if (null !== $broadcast) {
if (0 === $broadcast->getTimestampEnd()) {
$broadcast->setTimestampEnd($file->getMTime() ?: time());
}
$this->em->persist($broadcast);
$this->em->flush();
$tempPath = $file->getPathname();
$fs->uploadAndDeleteOriginal($tempPath, $recordingPath);
@ -91,7 +98,7 @@ class MoveBroadcastsTask extends AbstractTask
'Uploaded broadcast to storage location.',
[
'storageLocation' => (string)$storageLocation,
'path' => $recordingPath,
'path' => $recordingPath,
]
);
} else {
@ -100,7 +107,7 @@ class MoveBroadcastsTask extends AbstractTask
$this->logger->info(
'Could not find a corresponding broadcast.',
[
'path' => $recordingPath,
'path' => $recordingPath,
]
);
}