diff --git a/src/Options.php b/src/Options.php index 38a55a1..cf1ef00 100644 --- a/src/Options.php +++ b/src/Options.php @@ -230,6 +230,18 @@ class Options private ?string $convertSubsFormat = null; private bool $forceKeyframesAtCuts = false; + // Extractor Options + /** + * @var int|'infinite'|null + */ + private $extractorRetries; + private bool $allowDynamicMpd = false; + private bool $hlsSplitDiscontinuity = false; + /** + * @var array + */ + private array $extractorArgs = []; + /** * @var list */ @@ -1666,6 +1678,69 @@ public function convertSubsFormat(?string $subsFormat): self return $new; } + /** + * @param int|'infinite'|null $retries + */ + public function extractorRetries($retries): self + { + $new = clone $this; + $new->extractorRetries = $retries; + + return $new; + } + + /** + * Process dynamic DASH manifests. + */ + public function allowDynamicMpd(bool $allowDynamicMpd): self + { + $new = clone $this; + $new->allowDynamicMpd = $allowDynamicMpd; + + return $new; + } + + /** + * Split HLS playlists to different formats at discontinuities such as ad breaks. + */ + public function hlsSplitDiscontinuity(bool $hlsSplitDiscontinuity): self + { + $new = clone $this; + $new->hlsSplitDiscontinuity = $hlsSplitDiscontinuity; + + return $new; + } + + /** + * Pass args for a single extractor. + * + * @see https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#extractor-arguments + * + * @param non-empty-string $extractor + */ + public function extractorArgs(string $extractor, string $args): self + { + $new = clone $this; + $new->extractorArgs[$extractor] = $args; + + return $new; + } + + /** + * Pass args for all extractors. + * + * @see https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#extractor-arguments + * + * @param array $extractorArgs + */ + public function extractorsArgs(array $extractorArgs): self + { + $new = clone $this; + $new->extractorArgs = $extractorArgs; + + return $new; + } + /** * @param non-empty-string $url * @param non-empty-string ...$urls @@ -1825,6 +1900,12 @@ public function toArray(): array 'exec' => $this->exec, 'convert-subs-format' => $this->convertSubsFormat, 'force-keyframes-at-cuts' => $this->forceKeyframesAtCuts, + // Extractor Options + 'extractor-retries' => $this->extractorRetries, + 'allow-dynamic-mpd' => $this->allowDynamicMpd, + 'hls-split-discontinuity' => $this->hlsSplitDiscontinuity, + 'extractor-args' => $this->extractorArgs, + 'url' => $this->url, ]; } diff --git a/src/Process/ArgvBuilder.php b/src/Process/ArgvBuilder.php index e064092..6072b90 100644 --- a/src/Process/ArgvBuilder.php +++ b/src/Process/ArgvBuilder.php @@ -33,9 +33,9 @@ public static function build(Options $options): array if (count($value) > 0) { $cmd[] = sprintf('--%s=%s', $option, implode(',', $value)); } - } elseif ($option === 'add-header') { - foreach ($value as $header => $headerValue) { - $cmd[] = sprintf('--%s=%s:%s', $option, $header, $headerValue); + } elseif ($option === 'add-header' || $option === 'extractor-args') { + foreach ($value as $key => $v) { + $cmd[] = sprintf('--%s=%s:%s', $option, $key, $v); } } else { foreach ($value as $v) { diff --git a/tests/Process/ArgvBuilderTest.php b/tests/Process/ArgvBuilderTest.php index 0b9feed..74ee381 100644 --- a/tests/Process/ArgvBuilderTest.php +++ b/tests/Process/ArgvBuilderTest.php @@ -20,11 +20,15 @@ public function testFluentBuild(): void ->headers([ 'Accept' => 'text/html', ]) - ->header('User-Agent', 'youtube-downloader') + ->header('User-Agent', 'yt-dlp') ->yesPlaylist() ->playlistItems(['1-3', '7', '10-13']) ->dateBefore(new DateTimeImmutable('2020-08-31')) ->dateAfter(new DateTimeImmutable('2020-08-01')) + ->extractorsArgs([ + 'youtube' => 'player-client=mediaconnect,web;formats=incomplete', + ]) + ->extractorArgs('funimation', 'version=uncut') ->url( 'https://www.youtube.com/watch?v=-FZ-pPFAjYY', 'https://www.youtube.com/watch?v=Q-g_YNZ90tI', @@ -39,7 +43,9 @@ public function testFluentBuild(): void '--yes-playlist', '--output=/path/to/downloads/%(title)s-%(id)s.%(ext)s', '--add-header=Accept:text/html', - '--add-header=User-Agent:youtube-downloader', + '--add-header=User-Agent:yt-dlp', + '--extractor-args=youtube:player-client=mediaconnect,web;formats=incomplete', + '--extractor-args=funimation:version=uncut', 'https://www.youtube.com/watch?v=-FZ-pPFAjYY', 'https://www.youtube.com/watch?v=Q-g_YNZ90tI', ], ArgvBuilder::build($options));