mirror of
https://github.com/ihabunek/twitch-dl
synced 2024-08-30 18:32:25 +00:00
Add download --concat option
This commit is contained in:
parent
e228971f66
commit
7cc67133f5
@ -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()
|
||||||
|
@ -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>")
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user