yb¶
yb — streamline media publishing: prepare once, publish to YouTube or podcast.
Layered by separation of concerns:
core (always available):
yb.content— build a platform-neutralPublicationContent(title, description, keywords,chapters, captions, thumbnail) from a media file, delegating transcription, chapter detection, and thumbnails to the
mixingpackage.adapters (optional extras): -
yb.youtube(pip install 'yb[youtube]') — upload and edit videos. -yb.music(pip install 'yb[music]') — turn songs into music videos(rendering via
muvid) and publish them, including a whole folder as an album. Uploading also needsyb[youtube].yb.podcast(pip install 'yb[podcast]') — show notes, chapter markers, cover-over-audio video (viamuvid), RSS episode item.yb.download(pip install 'yb[download]') — fetch videos/metadata.
The audio→video rendering itself lives in muvid.visualize (yb is the
publication layer); yb.music is the thin publish-facing facade over it.
The most common callables are re-exported here for convenience; the ones that
live in optional extras are imported lazily, so import yb never fails for a
missing extra — the error surfaces only when you actually use that feature.
Examples
>>> import yb
>>> r = yb.download_youtube_video("https://youtu.be/PRa9ciOe-us") # needs yb[download]
>>> content = yb.prepare_content(r.path, language="English", language_code="en")
>>> yb.prepare_and_publish(r.path, privacy_status="unlisted") # needs yb[youtube]
- class yb.ContentMetadata(title, description, keywords=<factory>)[source]¶
Bases:
objectPlatform-neutral copy: a title, a description, and keywords.
- class yb.PublicationContent(media, title='', description='', keywords=<factory>, chapters=<factory>, language=None, audio_language=None, srt_path=None, thumbnail=None, duration=None)[source]¶
Bases:
objectEverything needed to publish a piece of media, destination-agnostic.
- media¶
Path to the audio/video file.
- title¶
Headline/title.
- description¶
Long-form description / show notes body.
- keywords¶
Topical keywords/tags.
- chapters¶
Ordered chapter markers (
mixing.chapters.Chapter).
- language¶
BCP-47 code of the metadata text (e.g.
"en").
- audio_language¶
BCP-47 code of the spoken audio (e.g.
"fr").
- srt_path¶
Path to the SRT subtitle/caption file, if any.
- thumbnail¶
Path to a thumbnail/cover image, if any.
- duration¶
Media duration in seconds, if known.
- class yb.YbConfig(privacy_status='unlisted', playlist=None, create_playlist_if_missing=True, playlist_privacy_status='private')[source]¶
Bases:
objectResolved publishing defaults.
- privacy_status¶
Privacy a new upload gets (
unlisted|private|public) when the call doesn’t override it.
- playlist¶
Title of a playlist every upload is added to (
None= none).
- create_playlist_if_missing¶
Create
playlistif no playlist of that title exists yet, rather than erroring.
- playlist_privacy_status¶
Privacy for an auto-created playlist.
- yb.add_video_to_playlist(video_id, title, *, create=True, privacy_status='private', skip_if_present=True, service=None, **cred_kwargs)[source]¶
Find-or-create the playlist named
titleand appendvideo_id.Idempotent: with
skip_if_present(default), a video already in the playlist is left alone instead of duplicated.
- yb.default_config_file()[source]¶
Config file location (
$XDG_CONFIG_HOMEor~/.config).- Return type:
- yb.download_youtube_audio(url, *, download_dir=None, audio_format=None, bitrate=None, keep_original=False, on_error='raise', fmt='bestaudio/best', filename_template='%(title)s (%(id)s).%(ext)s', write_info_json=False, write_thumbnail=False, write_description=False, write_subtitles=False, write_auto_subtitles=False, subtitle_langs=('en',), quiet=True, extra_opts=None, start=None, end=None, precise_cuts=False, cookies_file=None)[source]¶
Download only a video’s audio (no video stream).
Simplest use:
download_youtube_audio(url)→ the best audio stream, kept in whatever format the source offers (YouTube’s is usually Opus in a.webmcontainer), namedTitle (video_id).webmin~/Downloads.Pass
audio_formatto get a specific format instead:>>> download_youtube_audio(url, audio_format="mp3")
- Parameters:
url (
str) – The video URL (or id).download_dir (
str|Path|None) – Destination directory. Defaults todefault_download_dir().audio_format (
str|None) – Target format as an extension ("mp3",".wav", …). The defaultNonemeans no conversion — keep the downloaded bytes exactly as they came, which needs no ffmpeg and avoids re-encoding a lossy stream into another lossy format.bitrate (
str|None) – Bitrate for lossy targets (e.g."320k"). Ignored whenaudio_formatis lossless orNone.keep_original (
bool) – When converting, also keep the originally downloaded file (by default it is removed once converted).on_error (
Literal['raise','warn']) – What to do when conversion fails (ffmpeg missing or erroring)."raise"(default) propagatesAudioConversionError;"warn"emits a warning and returns the unconverted download. Either way the downloaded audio is left on disk — a failed conversion never costs you the download.fmt (
str) – yt-dlp format selector (default best audio-only stream).filename_template (
str) – yt-dlp output template (default"%(title)s (%(id)s).%(ext)s").write_info_json (
bool) – Also save the full metadata as*.info.json.write_thumbnail (
bool) – Also save the thumbnail image.write_description (
bool) – Also save the description as*.description.write_subtitles (
bool) – Also save uploaded subtitles forsubtitle_langs.write_auto_subtitles (
bool) – Also save auto-generated subtitles.subtitle_langs (
tuple[str,...]) – Subtitle languages to fetch when subtitles are enabled.quiet (
bool) – Suppress yt-dlp console output.extra_opts (
dict|None) – Any additional raw yt-dlp options (merged last, so they win).start (
int|float|str|None) –Download only a span, as in
download_youtube_video():>>> download_youtube_audio(url, start="0:07.9", end="0:08.75")
end (
int|float|str|None) –Download only a span, as in
download_youtube_video():>>> download_youtube_audio(url, start="0:07.9", end="0:08.75")
precise_cuts (
bool) –Download only a span, as in
download_youtube_video():>>> download_youtube_audio(url, start="0:07.9", end="0:08.75")
- Return type:
- Returns:
A
DownloadResultwhosepathis the audio file — converted whenaudio_formatwas given and conversion succeeded.- Raises:
ValueError – If
on_erroris not"raise"or"warn".AudioConversionError – If conversion fails and
on_error="raise".
- yb.download_youtube_video(url, *, download_dir=None, fmt='bestvideo+bestaudio/best', merge_to='mp4', filename_template='%(title)s (%(id)s).%(ext)s', write_info_json=False, write_thumbnail=False, write_description=False, write_subtitles=False, write_auto_subtitles=False, subtitle_langs=('en',), quiet=True, extra_opts=None, start=None, end=None, precise_cuts=False, cookies_file=None)[source]¶
Download a YouTube video to
download_dir(default~/Downloads).Simplest use:
download_youtube_video(url)→ best quality merged to mp4, namedTitle (video_id).mp4in~/Downloads.- Parameters:
url (
str) – The video URL (or id).download_dir (
str|Path|None) – Destination directory. Defaults todefault_download_dir().fmt (
str) – yt-dlp format selector (default best video + best audio).merge_to (
str|None) – Container to merge video+audio into (default"mp4"; requires ffmpeg). SetNoneto keep yt-dlp’s default.filename_template (
str) – yt-dlp output template (default"%(title)s (%(id)s).%(ext)s").write_info_json (
bool) – Also save the full metadata as*.info.json.write_thumbnail (
bool) – Also save the thumbnail image.write_description (
bool) – Also save the description as*.description.write_subtitles (
bool) – Also save uploaded subtitles forsubtitle_langs.write_auto_subtitles (
bool) – Also save auto-generated subtitles.subtitle_langs (
tuple[str,...]) – Subtitle languages to fetch when subtitles are enabled.quiet (
bool) – Suppress yt-dlp console output.extra_opts (
dict|None) – Any additional raw yt-dlp options (merged last, so they win).start (
int|float|str|None) – Download only this span: seconds (7.9) or a timestamp ("0:07.9","1:02:03"). Either may be given alone (endonly = from the beginning;startonly = to the end). The span is recorded ininfo["download_range"]as{"start", "end"}seconds (endisNonefor “to the end”), and, with the defaultfilename_template, in the filename (Title (id) [7.9-8.75].mp4) so a clip never collides with the full video. Needs ffmpeg (seeyb.download.ranges).end (
int|float|str|None) – Download only this span: seconds (7.9) or a timestamp ("0:07.9","1:02:03"). Either may be given alone (endonly = from the beginning;startonly = to the end). The span is recorded ininfo["download_range"]as{"start", "end"}seconds (endisNonefor “to the end”), and, with the defaultfilename_template, in the filename (Title (id) [7.9-8.75].mp4) so a clip never collides with the full video. Needs ffmpeg (seeyb.download.ranges).precise_cuts (
bool) – Withstart/end, re-encode at the cuts for frame-accurate bounds (slower) instead of cutting at keyframes.cookies_file (
Union[str,Path,Literal[False],None]) – Netscape-format cookies file to authenticate with (for headless servers wherecookies_from_browsercannot work). DefaultNonereads$YB_COOKIES_FILE, else~/.config/yb/youtube-cookies.txtif it exists, else sends no cookies. An explicitcookies_from_browserorextra_optscookie option suppresses that default;Falseopts out of it. The file is checked first (ValueErrorif explicit, else a warning, naming only line numbers). It cannot be combined with a browser cookie source. yt-dlp rewrites the file with refreshed cookies on exit, so it must be writable and not shared by parallel workers.
- Return type:
- Returns:
A
DownloadResultwith the media path, trimmedinfo, and anysidecarswritten.- Raises:
ValueError – If
start/endis not a timestamp, orendis not afterstart. Raised before anything is fetched or written.
- yb.format_chapter_lines(chapters)[source]¶
Render chapters as
M:SS Titlelines (the shared text convention).Uses
H:MM:SSwhen any chapter is at or beyond one hour. This is the text format both YouTube descriptions and podcast show notes accept.- Return type:
- yb.generate_metadata(transcript, *, language='English', brand=None, extra_context=None, model=None)[source]¶
Generate platform-neutral title/description/keywords from a transcript.
LLM-backed via
aix. Pass a readyContentMetadatatoprepare_content()instead if you want to skip generation.- Raises:
ImportError –
aixis not importable.- Return type:
- yb.load_config(config_file=None, **overrides)[source]¶
Load publishing defaults from
config_file(or the default location).A missing file yields the built-in defaults.
overrides(typically the explicit keyword arguments a caller passed) take precedence when notNone, so call-site arguments always win over the file.- Return type:
- yb.prepare_and_publish(media, *, language='English', language_code=None, audio_language_code=None, brand=None, extra_context=None, with_chapters=True, with_thumbnail=True, privacy_status=None, playlist=<object object>, category_id='28', config=None, client_secrets_file=None, token_file=None, progress=True, **cred_kwargs)[source]¶
One call: prepare publication content from
mediaand upload it.Transcribes (persisting the SRT next to the media) if needed, writes LLM metadata, detects chapters, renders a thumbnail, then uploads with captions + thumbnail + chapters and adds the video to the configured playlist.
privacy_statusandplaylistdefault to yourybconfig (seepublish_content()).cred_kwargsreachget_credentials()(e.g.open_browser=False, port=8080for headless consent).- Return type:
- yb.prepare_content(media, *, language='English', language_code=None, audio_language_code=None, brand=None, extra_context=None, transcript=None, with_chapters=True, with_thumbnail=False, thumbnail_text=None, metadata=None, model=None, transcribe_kwargs=None, chapters_kwargs=None)[source]¶
Build a
PublicationContentformedia(destination-agnostic).Ensures a persisted SRT next to the media (transcribing once via
mixingif needed), writes LLM metadata, detects chapters (default on, auto-skipped for clips too short to host them), and optionally renders a thumbnail. Any precomputed pieces (transcript,metadata) are reused instead of recomputed.- Parameters:
language (
str) – Human-readable language to write metadata in.audio_language_code (
str|None) – BCP-47 codes for the metadata text and the spoken audio.brand (
str|None) – Product/brand name to keep verbatim in the copy.extra_context (
str|None) – Extra guidance for the copywriter (audience, CTA…).transcript (
str|None) – SRT text to use as-is (skips transcription).with_chapters (
bool) – Detect chapters (defaultTrue).with_thumbnail (
bool) – Render a thumbnail image (defaultFalse).thumbnail_text (
str|None) – Overlay text for the thumbnail (defaults to the title).metadata (
ContentMetadata|None) – PrecomputedContentMetadatato reuse.chapters_kwargs (
dict|None) – Forwarded to the mixing calls.
- Return type:
- Returns:
A populated
PublicationContent.
- yb.prepare_podcast_episode(media, output_dir, *, content=None, audio=None, cover_image=None, make_cover_video=False, ken_burns=False, embed_chapters=True, language='English', brand=None, extra_context=None, audio_bitrate='192k')[source]¶
Build a podcast episode bundle from
mediaintooutput_dir.- Parameters:
output_dir (
str|Path) – Directory to write the episode assets into.content (
PublicationContent|None) – PrecomputedPublicationContent; built viayb.content.prepare_content()when omitted.audio (
str|Path|None) – Explicit episode audio. When omitted,mediais used if it is audio, else its audio track is extracted to MP3.cover_image (
str|Path|None) – Cover art (required formake_cover_video).make_cover_video (
bool) – Also render a cover-over-audio mp4 (e.g. for YouTube).ken_burns (
bool) – Apply a Ken Burns pan/zoom to the cover video.embed_chapters (
bool) – Embed ID3 chapter frames into the episode MP3.audio_bitrate (
str) – Bitrate for extracted MP3 audio.
- Return type:
- Returns:
A
PodcastEpisodewith the asset paths.
- yb.publish_content(content, *, privacy_status=None, playlist=<object object>, category_id='28', with_chapters=True, attach_caption=True, set_thumb=True, config=None, client_secrets_file=None, token_file=None, progress=True, service=None, resume=None, **cred_kwargs)[source]¶
Upload a prepared
PublicationContentto YouTube.Maps the content to a YouTube snippet (chapters embedded in the description when present), uploads, attaches the SRT caption track (language =
content.audio_languageorcontent.language) and the thumbnail when available, and adds the video to the configured playlist.privacy_statusandplaylistdefault to yourybconfig (seeyb.config): unset means “use the config value”, so privacy falls back tounlistedand the video joins your configured playlist. Passplaylist=Noneto skip the playlist for one call, orplaylist="Name"to override the target.cred_kwargsreachget_credentials()(e.g.open_browser=False, port=8080for headless consent).- Return type:
- Returns:
{"video_id", "url", "studio_url", "privacy_status", "captions", "thumbnail", "playlist"}.privacy_statusreflects what YouTube actually set (an unaudited project may force"private");playlistis theadd_video_to_playlist()result orNone.- Raises:
PartialPublish – the upload succeeded and a later step failed;
err.resultholds the video id and what was done. Passresume=err.resultto finish without uploading again (yb#21).
- yb.set_chapters(video_id, chapters, *, header='Chapters:', service=None, **cred_kwargs)[source]¶
Insert/replace a chapters block in the video’s description.
Strips any prior block under
headerand appends the new one. YouTube renders interactive chapters when the first timestamp is0:00.- Return type:
- yb.update_video_fields(video_id, *, title=None, description=None, tags=None, category_id=None, default_language=None, default_audio_language=None, service=None, **cred_kwargs)[source]¶
Patch selected snippet fields, preserving the rest.
Fetches the current snippet, overlays the provided fields, and updates.
categoryIdmust be present (kept from the existing snippet if not given).- Return type:
- yb.upsert_caption(video_id, track, *, language=None, name='', is_draft=False, replace=True, service=None, **cred_kwargs)[source]¶
Insert a caption track, or update the existing same-language one.
- Parameters:
video_id (
str) – Target video.track (
CaptionTrack|str|Path) – ACaptionTrack, or a path (thenlanguagerequired).replace (
bool) – When an uploaded track in the same language exists, update it (True, default) rather than inserting a duplicate.
- Return type:
- Returns:
The inserted/updated caption resource.
- yb.youtube_video_info(url, *, extra_opts=None, cookies_file=None)[source]¶
Fetch a video’s metadata without downloading it.
Returns the trimmed info dict (see
_INFO_FIELDS). Useful to preview the title/duration/chapters before deciding to download.cookies_file: seedownload_youtube_video().
Modules
Convert audio files between formats with ffmpeg. |
|
User configuration for |
|
Target-agnostic publication content: prepare it once, publish anywhere. |
|
Media download (yt-dlp) — fetch videos, audio, and their metadata. |
|
Podcast publishing: show notes, chapters, cover video, and RSS. |
|
YouTube publishing via the YouTube Data API v3. |