mirror of https://github.com/yutto-dev/yutto
parent
a3b63ef23c
commit
86c88b2bdf
|
@ -123,6 +123,7 @@ dmypy.json
|
|||
*.flac
|
||||
*.mp4
|
||||
*.mkv
|
||||
*.mov
|
||||
*.m4s
|
||||
*.xml
|
||||
*.pb
|
||||
|
|
26
README.md
26
README.md
|
@ -211,6 +211,32 @@ yutto 支持一些基础参数,无论是批量下载还是单视频下载都
|
|||
|
||||
详情同视频编码。
|
||||
|
||||
#### 指定输出格式
|
||||
|
||||
- 参数 `--output-format`
|
||||
- 可选值 `"infer" | "mp4" | "mkv" | "mov"`
|
||||
- 默认值 `"infer"`
|
||||
|
||||
在至少包含视频流时所使用的输出格式,默认选值 `"infer"` 表示自动根据情况进行推导以保证输出的可用,推导规则如下:
|
||||
|
||||
- 如果输出包含音频流且音频流编码为 `"fLaC"`,则输出格式为 `"mkv"`,因为 `"mp4"` 尚不支持 `"fLaC"` 编码
|
||||
- 否则为 `"mp4"`
|
||||
|
||||
#### 指定在仅包含音频流时的输出格式
|
||||
|
||||
- 参数 `--output-format-audio-only`
|
||||
- 可选值 `"infer" | "aac" | "flac" | "mp4" | "mkv" | "mov"`
|
||||
- 默认值 `"infer"`
|
||||
|
||||
在仅包含音频流时所使用的输出格式,默认选值 `"infer"` 表示自动根据情况进行推导以保证输出的可用,推导规则如下:
|
||||
|
||||
- 如果音频流编码为 `"fLaC"`,则输出格式为 `"flac"`
|
||||
- 否则为 `"aac"`
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> 并不是仅仅在指定 `--audio-only` 时才会仅仅包含视频流,有些视频是仅包含音频流的,此时即便不指定 `--audio-only` 选项也会按照本选项的格式进行输出。
|
||||
|
||||
#### 弹幕格式选择
|
||||
|
||||
- 参数 `-df` 或 `--danmaku-format`
|
||||
|
|
1
justfile
1
justfile
|
@ -41,6 +41,7 @@ clean:
|
|||
find . -name "*.m4s" -print0 | xargs -0 rm -f
|
||||
find . -name "*.mp4" -print0 | xargs -0 rm -f
|
||||
find . -name "*.mkv" -print0 | xargs -0 rm -f
|
||||
find . -name "*.mov" -print0 | xargs -0 rm -f
|
||||
find . -name "*.aac" -print0 | xargs -0 rm -f
|
||||
find . -name "*.flac" -print0 | xargs -0 rm -f
|
||||
find . -name "*.srt" -print0 | xargs -0 rm -f
|
||||
|
|
|
@ -85,6 +85,15 @@ def cli() -> argparse.ArgumentParser:
|
|||
group_common.add_argument(
|
||||
"--acodec", default="mp4a:copy", metavar="DOWNLOAD_ACODEC:SAVE_ACODEC", help="音频编码格式(<下载格式>:<生成格式>)"
|
||||
)
|
||||
group_common.add_argument(
|
||||
"--output-format", default="infer", choices=["infer", "mp4", "mkv", "mov"], help="输出格式(infer 为自动推断)"
|
||||
)
|
||||
group_common.add_argument(
|
||||
"--output-format-audio-only",
|
||||
default="infer",
|
||||
choices=["infer", "aac", "flac", "mp4", "mkv", "mov"],
|
||||
help="仅包含音频流时所使用的输出格式(infer 为自动推断)",
|
||||
)
|
||||
group_common.add_argument("-df", "--danmaku-format", default="ass", choices=["xml", "ass", "protobuf"], help="弹幕类型")
|
||||
group_common.add_argument("-bs", "--block-size", default=0.5, type=float, help="分块下载时各块大小,单位为 MiB,默认为 0.5MiB")
|
||||
group_common.add_argument("-w", "--overwrite", action="store_true", help="强制覆盖已下载内容")
|
||||
|
@ -258,6 +267,8 @@ async def run(args_list: list[argparse.Namespace]):
|
|||
"audio_quality": args.audio_quality,
|
||||
"audio_download_codec": args.acodec.split(":")[0],
|
||||
"audio_save_codec": args.acodec.split(":")[1],
|
||||
"output_format": args.output_format,
|
||||
"output_format_audio_only": args.output_format_audio_only,
|
||||
"overwrite": args.overwrite,
|
||||
"block_size": int(args.block_size * 1024 * 1024),
|
||||
"num_workers": args.num_workers,
|
||||
|
|
|
@ -179,6 +179,8 @@ class DownloaderOptions(TypedDict):
|
|||
audio_quality: AudioQuality
|
||||
audio_download_codec: AudioCodec
|
||||
audio_save_codec: str
|
||||
output_format: str
|
||||
output_format_audio_only: str
|
||||
overwrite: bool
|
||||
block_size: int
|
||||
num_workers: int
|
||||
|
|
|
@ -147,6 +147,15 @@ def merge_video_and_audio(
|
|||
ffmpeg = FFmpeg()
|
||||
Logger.info("开始合并……")
|
||||
|
||||
# Using FFmpeg to Create HEVC Videos That Work on Apple Devices:
|
||||
# https://aaron.cc/ffmpeg-hevc-apple-devices/
|
||||
# see also: https://github.com/yutto-dev/yutto/issues/85
|
||||
vtag: str | None = None
|
||||
if options["video_save_codec"] == "hevc" or (
|
||||
options["video_save_codec"] == "copy" and video is not None and video["codec"] == "hevc"
|
||||
):
|
||||
vtag = "hvc1"
|
||||
|
||||
if video is not None and video["codec"] == options["video_save_codec"]:
|
||||
options["video_save_codec"] = "copy"
|
||||
if audio is not None and audio["codec"] == options["audio_save_codec"]:
|
||||
|
@ -159,6 +168,7 @@ def merge_video_and_audio(
|
|||
["-acodec", options["audio_save_codec"]] if audio is not None else [],
|
||||
# see also: https://www.reddit.com/r/ffmpeg/comments/qe7oq1/comment/hi0bmic/?utm_source=share&utm_medium=web2x&context=3
|
||||
["-strict", "unofficial"],
|
||||
["-tag:v", vtag] if vtag is not None else [],
|
||||
["-threads", str(os.cpu_count())],
|
||||
["-y", str(output_path)],
|
||||
]
|
||||
|
@ -201,18 +211,26 @@ async def start_downloader(
|
|||
will_download_audio = audio is not None and require_audio
|
||||
|
||||
# 显示音视频详细信息
|
||||
show_videos_info(videos, videos.index(video) if video is not None else -1)
|
||||
show_audios_info(audios, audios.index(audio) if audio is not None else -1)
|
||||
show_videos_info(
|
||||
videos, videos.index(video) if will_download_video else -1 # pyright: ignore [reportGeneralTypeIssues]
|
||||
)
|
||||
show_audios_info(
|
||||
audios, audios.index(audio) if will_download_audio else -1 # pyright: ignore [reportGeneralTypeIssues]
|
||||
)
|
||||
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
output_format = ".mp4"
|
||||
if not will_download_video:
|
||||
if will_download_audio and audio["codec"] == "fLaC": # type: ignore
|
||||
if options["output_format_audio_only"] != "infer":
|
||||
output_format = "." + options["output_format_audio_only"]
|
||||
elif will_download_audio and audio["codec"] == "fLaC": # pyright: ignore [reportOptionalSubscript]
|
||||
output_format = ".flac"
|
||||
else:
|
||||
output_format = ".aac"
|
||||
else:
|
||||
if will_download_audio and audio["codec"] == "fLaC": # type: ignore
|
||||
if options["output_format"] != "infer":
|
||||
output_format = "." + options["output_format"]
|
||||
elif will_download_audio and audio["codec"] == "fLaC": # pyright: ignore [reportOptionalSubscript]
|
||||
output_format = ".mkv" # MP4 does not support FLAC audio
|
||||
|
||||
output_path = output_dir.joinpath(filename + output_format)
|
||||
|
@ -253,6 +271,9 @@ async def start_downloader(
|
|||
Logger.warning("没有音视频需要下载")
|
||||
return
|
||||
|
||||
video = video if will_download_video else None
|
||||
audio = audio if will_download_audio else None
|
||||
|
||||
# 下载视频 / 音频
|
||||
await download_video_and_audio(session, video, video_path, audio, audio_path, options)
|
||||
|
||||
|
|
Loading…
Reference in New Issue