aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJuhani Krekelä2024-09-12 22:53:49 +0300
committerWolfgang Müller2024-09-12 22:55:36 +0200
commitc2c30adb28c5f7a41c476261a7519b37ca952ffe (patch)
tree411e3c64be735c551806d34cdea8496778a36367
parent332102b598f35392f6e3cdd7d368824ec01dad74 (diff)
downloadlater-c2c30adb28c5f7a41c476261a7519b37ca952ffe.tar.gz
Show video titles using yt-dlp
Different video URLs can be easy to confuse in the output of later(1). Look up titles for them in $XDG_CACHE_HOME/later/title.json and add an option, --update-titles, to populate the file automatically using yt-dlp. The title is prefixed with a hash sign (#) in order to better separate it visually from the URLs, as well as to allow easier copypasting of output onto an mpv command line.
-rw-r--r--LICENSE2
-rwxr-xr-xlater81
-rw-r--r--later.127
3 files changed, 104 insertions, 6 deletions
diff --git a/LICENSE b/LICENSE
index 36c1528..00b6ce6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
ISC License
-Copyright (c) 2024 Wolfgang Müller
+Copyright (c) 2024 Wolfgang Müller, Juhani Krekelä
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/later b/later
index ef1ea55..ff7c478 100755
--- a/later
+++ b/later
@@ -1,8 +1,11 @@
#!/usr/bin/env python3
+import argparse
import datetime
+import json
import os
-import argparse
+import re
+import sys
from datetime import datetime as dt
@@ -12,6 +15,24 @@ if "XDG_STATE_HOME" in os.environ:
watch_later_dir = os.path.join(xdg_state_home, "mpv/watch_later")
+xdg_cache_home = os.path.expanduser("~/.cache")
+if "XDG_CACHE_HOME" in os.environ:
+ xdg_cache_home = os.environ["XDG_CACHE_HOME"]
+
+later_cache_dir = os.path.join(xdg_cache_home, "later")
+title_map_file = os.path.join(later_cache_dir, "titles.json")
+
+
+class YTDLPLogger:
+ def debug(self, msg):
+ pass
+
+ def warning(self, msg):
+ pass
+
+ def error(self, msg):
+ print("later: yt-dlp:", msg, file=sys.stderr)
+
def entries():
def get_mtime(entry):
@@ -27,8 +48,35 @@ def entries():
parser = argparse.ArgumentParser(
prog="later", description="List mpv's watch_later entries"
)
+parser.add_argument(
+ "-u",
+ "--update-titles",
+ action="store_true",
+ help="update titles of videos using yt-dlp",
+)
args = parser.parse_args()
+if args.update_titles:
+ import yt_dlp
+
+ yt_dlp_opts = {
+ "logger": YTDLPLogger(),
+ }
+ ytdl = yt_dlp.YoutubeDL(yt_dlp_opts)
+
+write_title_map = args.update_titles
+
+try:
+ with open(title_map_file, "r") as handle:
+ title_map = json.load(handle)
+except FileNotFoundError:
+ title_map = {}
+except json.decoder.JSONDecodeError:
+ title_map = {}
+ write_title_map = True
+except Exception as err:
+ sys.exit(f"later: {err}")
+
for path, basename, mtime in entries():
with open(path, "r") as handle:
first = handle.readline().rstrip()
@@ -40,10 +88,39 @@ for path, basename, mtime in entries():
if name == "redirect entry":
continue
+ if args.update_titles and name not in title_map:
+ if re.fullmatch(r"https?://.*", name):
+ try:
+ info = ytdl.extract_info(name, download=False)
+
+ # The generic extractor uses the filename part of the url as the
+ # title. Since we already display the URL, this adds no extra
+ # information.
+ if info["extractor"] == "generic":
+ title_map[name] = ""
+ else:
+ title_map[name] = info["title"]
+
+ except yt_dlp.utils.DownloadError:
+ pass
+
def format_time(time):
now = dt.now()
if time < now - datetime.timedelta(days=7):
return time.strftime("%b %d %Y")
return time.strftime("%b %d %H:%M")
- print(f"{format_time(mtime)}\t{name}")
+ output = [format_time(mtime), name]
+
+ if title := title_map.get(name):
+ output.append("# " + title)
+
+ print(*output, sep="\t")
+
+if write_title_map:
+ try:
+ os.mkdir(later_cache_dir)
+ except FileExistsError:
+ pass
+ with open(title_map_file, "w") as handle:
+ json.dump(title_map, handle)
diff --git a/later.1 b/later.1
index 6b2bec9..c0ba5e5 100644
--- a/later.1
+++ b/later.1
@@ -1,4 +1,4 @@
-.Dd September 10, 2024
+.Dd September 12, 2024
.Dt LATER 1
.Os
.Sh NAME
@@ -6,12 +6,31 @@
.Nd list mpv's watch_later entries
.Sh SYNOPSIS
.Nm
-.Op Fl h
-.Op Fl \-help
+.Op Fl u | \-update-titles
+.Nm
+.Fl h | \-help
.Sh DESCRIPTION
.Nm
lists all watch_later entries as saved by
.Xr mpv 1 .
+.Pp
+The options are as follows:
+.Bl -tag -width "-h, --update-titles"
+.It Fl u , Fl \-update-titles
+update titles of videos using yt-dlp
+.It Fl h , Fl \-help
+show a conscise help message
+.El
+.Sh FILES
+.Bl -tag -width "1"
+.It Pa $XDG_CACHE_HOME/later/titles.json
+JSON-encoded mapping of URLs to video titles.
+Populated by running
+.Nm
+with the
+.Fl \-update-titles
+option.
+.El
.Sh SEE ALSO
.Xr mpv 1
.Sh AUTHORS
@@ -19,3 +38,5 @@ lists all watch_later entries as saved by
.Nm
was written by
.An Wolfgang Müller Aq Mt wolf@oriole.systems
+with yt-dlp integration by
+.An Juhani Krekelä Aq Mt juhani@krekelä.fi