Add download --concat option

This commit is contained in:
Ivan Habunek 2024-03-29 08:24:45 +01:00
parent e228971f66
commit 7cc67133f5
No known key found for this signature in database
GPG Key ID: F5F0623FF5EBCB3D
3 changed files with 38 additions and 9 deletions

View File

@ -173,6 +173,11 @@ def clips(
is_flag=False, is_flag=False,
flag_value=0, flag_value=0,
) )
@click.option(
"--concat",
is_flag=True,
help="Do not use ffmpeg to join files, concat them instead",
)
@click.option( @click.option(
"-d", "-d",
"--dry-run", "--dry-run",
@ -188,8 +193,9 @@ def clips(
@click.option( @click.option(
"-f", "-f",
"--format", "--format",
help="Video format to convert into, passed to ffmpeg as the target file extension.", help="""Video format to convert into, passed to ffmpeg as the target file
default="mkv", extension. Defaults to `mkv`. If `--concat` is passed, defaults to
`ts`.""",
) )
@click.option( @click.option(
"-k", "-k",
@ -241,6 +247,7 @@ def download(
ids: tuple[str, ...], ids: tuple[str, ...],
auth_token: str | None, auth_token: str | None,
chapter: int | None, chapter: int | None,
concat: bool,
dry_run: bool, dry_run: bool,
end: int | None, end: int | None,
format: str, format: str,
@ -257,10 +264,15 @@ def download(
Pass one or more video ID, clip slug or Twitch URL to download. Pass one or more video ID, clip slug or Twitch URL to download.
""" """
from twitchdl.commands.download import download
if not format:
format = "ts" if concat else "mkv"
options = DownloadOptions( options = DownloadOptions(
auth_token=auth_token, auth_token=auth_token,
chapter=chapter, chapter=chapter,
concat=concat,
dry_run=dry_run, dry_run=dry_run,
end=end, end=end,
format=format, format=format,
@ -274,8 +286,7 @@ def download(
max_workers=max_workers, max_workers=max_workers,
) )
from twitchdl.commands.download import download download(list(ids), options)
download(ids, options)
@cli.command() @cli.command()

View File

@ -1,4 +1,6 @@
import asyncio import asyncio
import platform
import click
import httpx import httpx
import m3u8 import m3u8
import os import os
@ -20,7 +22,7 @@ from twitchdl.http import download_all
from twitchdl.output import print_out from twitchdl.output import print_out
def download(ids, args: DownloadOptions): def download(ids: list[str], args: DownloadOptions):
for video_id in ids: for video_id in ids:
download_one(video_id, args) download_one(video_id, args)
@ -78,7 +80,7 @@ def _select_playlist_interactive(playlists):
return uri return uri
def _join_vods(playlist_path, target, overwrite, video): def _join_vods(playlist_path: str, target: str, overwrite: bool, video):
command = [ command = [
"ffmpeg", "ffmpeg",
"-i", playlist_path, "-i", playlist_path,
@ -99,6 +101,15 @@ def _join_vods(playlist_path, target, overwrite, video):
if result.returncode != 0: if result.returncode != 0:
raise ConsoleError("Joining files failed") raise ConsoleError("Joining files failed")
def _concat_vods(vod_paths: list[str], target: str):
tool = "type" if platform.system() == "Windows" else "cat"
command = [tool] + vod_paths
with open(target, "wb") as target_file:
result = subprocess.run(command, stdout=target_file)
if result.returncode != 0:
raise ConsoleError(f"Joining files failed: {result.stderr}")
def _video_target_filename(video, args: DownloadOptions): def _video_target_filename(video, args: DownloadOptions):
date, time = video['publishedAt'].split("T") date, time = video['publishedAt'].split("T")
@ -335,13 +346,19 @@ def _download_video(video_id, args: DownloadOptions) -> None:
playlist_path = path.join(target_dir, "playlist_downloaded.m3u8") playlist_path = path.join(target_dir, "playlist_downloaded.m3u8")
playlist.dump(playlist_path) playlist.dump(playlist_path)
print_out("")
if args.no_join: if args.no_join:
print_out("\n\n<dim>Skipping joining files...</dim>") print_out("<dim>Skipping joining files...</dim>")
print_out(f"VODs downloaded to:\n<blue>{target_dir}</blue>") print_out(f"VODs downloaded to:\n<blue>{target_dir}</blue>")
return return
print_out("\n\nJoining files...") if args.concat:
_join_vods(playlist_path, target, args.overwrite, video) print_out("<dim>Concating files...</dim>")
_concat_vods(targets, target)
else:
print_out("<dim>Joining files...</dim>")
_join_vods(playlist_path, target, args.overwrite, video)
if args.keep: if args.keep:
print_out(f"\n<dim>Temporary files not deleted: {target_dir}</dim>") print_out(f"\n<dim>Temporary files not deleted: {target_dir}</dim>")

View File

@ -5,6 +5,7 @@ from dataclasses import dataclass
class DownloadOptions: class DownloadOptions:
auth_token: str | None auth_token: str | None
chapter: int | None chapter: int | None
concat: bool
dry_run: bool dry_run: bool
end: int | None end: int | None
format: str format: str