Skip to content

Commit

Permalink
Update commmands
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurujai committed Mar 8, 2024
1 parent fd27e14 commit df3770f
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 155 deletions.
5 changes: 0 additions & 5 deletions .idea/.gitignore

This file was deleted.

10 changes: 0 additions & 10 deletions .idea/PumukitYoutubeBundle.iml

This file was deleted.

8 changes: 0 additions & 8 deletions .idea/modules.xml

This file was deleted.

22 changes: 0 additions & 22 deletions .idea/php.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

140 changes: 45 additions & 95 deletions Command/DownloadVideosFromYouTubeChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Doctrine\ODM\MongoDB\DocumentManager;
use Pumukit\EncoderBundle\Document\Job;
use Pumukit\SchemaBundle\Document\MultimediaObject;
use Pumukit\SchemaBundle\Document\Series;
use Pumukit\SchemaBundle\Document\Tag;
use Pumukit\YoutubeBundle\Services\GoogleAccountService;
use Symfony\Component\Console\Command\Command;
Expand All @@ -27,6 +28,7 @@ final class DownloadVideosFromYouTubeChannel extends Command
private DocumentManager $documentManager;
private GoogleAccountService $googleAccountService;
private string $tempDir;
private array $youtubeErrors = [];

public function __construct(DocumentManager $documentManager, GoogleAccountService $googleAccountService, string $tempDir)
{
Expand All @@ -40,24 +42,9 @@ protected function configure(): void
{
$this
->setName('pumukit:youtube:download:videos:from:channel')
->addOption(
'account',
null,
InputOption::VALUE_REQUIRED,
'Account'
)
->addOption(
'channel',
null,
InputOption::VALUE_REQUIRED,
'Channel ID'
)
->addOption(
'limit',
null,
InputOption::VALUE_OPTIONAL,
'limit'
)
->addOption('account', null, InputOption::VALUE_REQUIRED, 'Account')
->addOption('channel', null, InputOption::VALUE_REQUIRED, 'Channel ID')
->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'limit')
->setDescription('Import all videos from Youtube channel')
->setHelp(
<<<'EOT'
Expand All @@ -76,75 +63,61 @@ protected function configure(): void
protected function execute(InputInterface $input, OutputInterface $output): int
{
$channel = $input->getOption('channel');
$limit = (int) $input->getOption('limit');

$youtubeAccount = $this->ensureYouTubeAccountExists($input);

$service = $this->googleAccountService->googleServiceFromAccount($youtubeAccount);
$channelId = $this->channelId($channel, $service);
$multimediaObjects = $this->documentManager->getRepository(MultimediaObject::class)->findBy([
'status' => ['$in' => [MultimediaObject::STATUS_PUBLISHED, MultimediaObject::STATUS_HIDDEN]],
'properties.youtube_import_status' => ['$exists' => false],
'properties.youtube_import_channel' => $channel,
], [], $limit ?? null);

$nextPageToken = null;
$count = 0;
$queryParams = [
'type' => 'video',
'forMine' => true,
'maxResults' => 50,
];

$response = $service->search->listSearch('snippet', $queryParams);

$progressBar = new ProgressBar($output, $response->pageInfo->getTotalResults());
$progressBar = new ProgressBar($output, count($multimediaObjects));
$progressBar->start();

do {
$count = 0;
foreach($multimediaObjects as $multimediaObject) {
$progressBar->advance();
if (null !== $input->getOption('limit') && $count >= $input->getOption('limit')) {
break;
}
$count++;

if (null !== $nextPageToken) {
$queryParams['pageToken'] = $nextPageToken;
$videoId = $multimediaObject->getProperty('youtube_import_id');
$youtubeDownloader = new YouTubeDownloader();

$youtubeURL = self::BASE_URL_YOUTUBE_VIDEO.$videoId;
$downloadOptions = $youtubeDownloader->getDownloadLinks($youtubeURL);

if (empty($downloadOptions->getAllFormats())) {
$multimediaObject->setProperty('youtube_download_info', json_encode($downloadOptions));
$this->documentManager->flush();

$this->youtubeErrors[] = 'URL: '.$youtubeURL.' no formats found. Formats: '.json_encode($downloadOptions->getAllFormats());

continue;
}

$service = $this->googleAccountService->googleServiceFromAccount($youtubeAccount);
$response = $service->search->listSearch('snippet', $queryParams);
$nextPageToken = $response->getNextPageToken();

foreach ($response->getItems() as $item) {
$progressBar->advance();
if (null !== $input->getOption('limit') && $count >= $input->getOption('limit')) {
break;
}
++$count;
$videoId = $item->getId()->getVideoId();
$youtubeDownloader = new YouTubeDownloader();

try {
$youtubeURL = self::BASE_URL_YOUTUBE_VIDEO.$videoId;
$downloadOptions = $youtubeDownloader->getDownloadLinks($youtubeURL);

if (empty($downloadOptions->getAllFormats())) {
$output->writeln('URL: '.$youtubeURL.' no formats found.');

continue;
}

$url = $this->selectBestStreamFormat($downloadOptions);

try {
$this->moveFileToStorage($item, $url, $downloadOptions, $channelId);
} catch (\Exception $exception) {
$output->writeln('Error moving file to storage: '.$exception->getMessage());
}
} catch (YouTubeException $e) {
$output->writeln('There was error downloaded video with title '.$item->snippet->title.' and id '.$videoId);

continue;
}
$url = $this->selectBestStreamFormat($downloadOptions);

try {
$this->moveFileToStorage($multimediaObject, $url, $downloadOptions, $channel);
$multimediaObject->setProperty('youtube_import_status', 'downloaded');
$this->documentManager->flush();
} catch (\Exception $exception) {
$this->youtubeErrors[] = 'Error moving file to storage: '.$exception->getMessage();
continue;
}
} while (null !== $nextPageToken);
}

$progressBar->finish();
$output->writeln(' ');

foreach ($this->youtubeErrors as $error) {
$output->writeln($error);
}

return 0;
}

Expand Down Expand Up @@ -201,26 +174,13 @@ private function selectBestStreamFormat(DownloadOptions $downloadOptions): ?Stre
return null;
}

private function moveFileToStorage($item, $url, DownloadOptions $downloadOptions, string $channelId): void
private function moveFileToStorage(MultimediaObject $multimediaObject, $url, DownloadOptions $downloadOptions, string $channelId): void
{
$videoId = $item->getId()->getVideoId();
$videoId = $multimediaObject->getProperty('youtube_import_id');
$mimeType = explode('video/', $this->selectBestStreamFormat($downloadOptions)->getCleanMimeType())[1];
$this->createChannelDir($channelId);
$file = $this->tempDir.'/'.$channelId.'/'.$videoId.'.'.$mimeType;

$multimediaObject = $this->documentManager->getRepository(MultimediaObject::class)->findOneBy([
'properties.youtube_import_id' => $videoId,
]);

$failedJobs = $this->documentManager->getRepository(Job::class)->findOneBy([
'status' => Job::STATUS_ERROR,
'mm_id' => $multimediaObject,
]);

if (!file_exists($file) && $multimediaObject instanceof MultimediaObject && !$failedJobs instanceof Job) {
return;
}

$content = file_get_contents($url->url);

file_put_contents($file, $content);
Expand All @@ -246,14 +206,4 @@ private function ensureYouTubeAccountExists(InputInterface $input): Tag
return $youtubeAccount;
}

private function channelId(string $channel, \Google_Service_YouTube $service): string
{
$queryParams = [
'id' => $channel,
];

$channels = $service->channels->listChannels('snippet', $queryParams);

return $channels->getItems()[0]->getId();
}
}
7 changes: 1 addition & 6 deletions Command/ImportVideosFromYouTubeChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ protected function configure(): void
->addOption('account', null, InputOption::VALUE_REQUIRED, 'Account')
->addOption('channel', null, InputOption::VALUE_REQUIRED, 'Channel ID')
->addOption('limit', null, InputOption::VALUE_OPTIONAL, 'limit')
->addOption('live', null, InputOption::VALUE_OPTIONAL, 'Import lives instead of videos')
->setDescription('Import all videos from Youtube channel')
->setHelp(
<<<'EOT'
Expand All @@ -87,11 +86,7 @@ protected function configure(): void
Limit is optional to test the command.
Usage: php bin/console pumukit:youtube:import:videos:from:channel --account={ACCOUNT} --channel={CHANNEL_ID} --limit={LIMIT} --live
To import live instead of videos use --live param
Usage: php bin/console pumukit:youtube:import:videos:from:channel --account={ACCOUNT} --channel={CHANNEL_ID} --limit={LIMIT} --live
Usage: php bin/console pumukit:youtube:import:videos:from:channel --account={ACCOUNT} --channel={CHANNEL_ID} --limit={LIMIT}

EOT
)
Expand Down
4 changes: 2 additions & 2 deletions Resources/doc/ImportFromYoutube.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ where ACCOUNT is the name added for YouTube tag created on PuMuKIT and CHANNEL_I

### 2. Import videos from YouTube

Before download videos you will be able to import videos from YouTube to PuMuKIT using this command.
Import videos metadata from YouTube

The command will be autocomplete metadata from YouTube and create a new video on PuMuKIT and move the video to the series created on step 1.
The command creates a new video on PuMuKIT for each video on YouTube and move it to the series created on step 1.

```
php bin/console pumukit:youtube:import:videos:from:channel --account={ACCOUNT} --channel={CHANNEL_ID}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}
],
"require": {
"php": "^7.4 || ^8.2",
"php": "^8.2",
"pumukit/pumukit": ">4.0",
"google/apiclient" : "^2.0",
"athlon1600/youtube-downloader": "^4.0"
Expand Down

0 comments on commit df3770f

Please sign in to comment.