Last active
January 12, 2024 16:20
-
-
Save we-taper/96792114f267fc8fcf21807b0e216ffd to your computer and use it in GitHub Desktop.
Extract chapters part of the Youtube-dl's json info into a CUE file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! python3 | |
""" | |
Extract chapters part of the Youtube-dl's json info into a CUE file. | |
This file is in the public domain. | |
Requirements: | |
pydantic | |
python>=3.6 | |
Steps: | |
1. Download JSON information (`--skip-download` skips downloading the video/audio): | |
`youtube-dl --skip-download --write-info-json YouTubeURL` | |
2. Generate CUE file: `ydljson2cue.py json_filename [optional video/audio extension]` | |
""" | |
from pathlib import Path | |
from pydantic import BaseModel | |
from typing import List, Union | |
import os | |
class Chapter(BaseModel): | |
start_time: int | |
end_time: int | |
title: str | |
def to_cue_data(chapter: Chapter, idx: int) -> List[str]: | |
return [ | |
f" TRACK {idx:02d} AUDIO", | |
f' TITLE "{chapter.title}"', | |
f" INDEX 01 {chapter.start_time // 60}:{chapter.start_time % 60}:00", | |
] | |
class YoutubeDlInfoJson(BaseModel): | |
chapters: List[Chapter] | |
title: str | |
class Config: | |
ignore_extra = True | |
def convert(ydl_info: YoutubeDlInfoJson, output_file): | |
cue_data = [ | |
f'TITLE "{ydl_info.title}"', | |
f'FILE "{output_file}" WAVE', | |
] | |
for idx, chapter in enumerate(ydl_info.chapters): | |
cue_data.extend(to_cue_data(chapter, idx + 1)) | |
return cue_data | |
def read_and_write(input: Union[str, Path], ext="mp3"): | |
input = Path(input) | |
basename = os.path.splitext(input)[0] | |
output = input.parent / f"{basename}.cue" | |
ydl_info = YoutubeDlInfoJson.parse_file(input) | |
cue_data = convert(ydl_info, input.parent / f"{basename}.{ext}") | |
output.write_text(os.linesep.join(cue_data)) | |
if __name__ == "__main__": | |
import sys | |
argv_len = len(sys.argv) | |
if argv_len == 2: | |
file = sys.argv[1] | |
ext = "mp3" | |
elif argv_len == 3: | |
file, ext = sys.argv[1:] | |
else: | |
print("Usage: script_name json_filename [extension]", file=sys.stderr) | |
sys.exit(1) | |
read_and_write(file, ext) |
@6b6561 Thanks. In response to Pydantic's change, maybe replace that piece of code by first load the file into dict
with python's json
library, and then convert it to YoutubeDlInfoJson
with YoutubeDlInfoJson.model_validate
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I tried your script which runs properly but giving a warning with pydantic-2.5.3 which was installed by pip.
$ python3 ydljson2cue.py test.json ydljson2cue.py:59: PydanticDeprecatedSince20: The
parse_filemethod is deprecated; load the data from file, then if your data is JSON use
model_validate_json, otherwise
model_validateinstead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.5/migration/ ydl_info = YoutubeDlInfoJson.parse_file(input)