From: Joseph Nuthalapati Date: Fri, 9 Feb 2024 04:57:42 +0000 (+0530) Subject: update TODO list X-Git-Url: https://njoseph.me/gitweb/nimcoon.git/commitdiff_plain/HEAD?hp=ff0a15bf2f06bd2380dce5c5584c5d871346a3c9 update TODO list --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 301fbdf..22a8187 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.9.0 + +- Replace youtube-dl with yt-dlp. Though this fixes the problem with YouTube throttling download speeds, it doesn't fix the throttling during streaming since mpv and vlc are still using youtube-dl. mpv has provided an option to provide an alternative youtube-dl implementation. Waiting for VLC to implement the same. +- Shift to PeerTube's new videoId format. Support for the UUID format is dropped. +- Dropped Peerflix as a dependency. WebTorrent is faster and better. They also added support for video player arguments on my request. See https://github.com/webtorrent/webtorrent-cli/issues/141 + # 0.8.3 - Add fake user-agent diff --git a/README.md b/README.md index 2b09f97..6e88ecf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NimCoon +# Nimcoon Play videos from YouTube and PeerTube from the command line using your preferred desktop media player. @@ -28,7 +28,7 @@ I tried all kinds of alternative YouTube players for the desktop. Most are eithe YouTube's business incentive is to make you watch as many videos as possible. If you open the YouTube website and are logged into it, you will just get distracted by recommendations and forget why you opened it in the first place. You might have wanted to watch a conference talk but end up going down a rabbit hole of other "interesting" videos customized for you. -NimCoon has a spartan design. It doesn't even show images of the search results. It doesn't let you browse YouTube. You have to explicitly search for something. +Nimcoon has a spartan design. It doesn't even show images of the search results. It doesn't let you browse YouTube. You have to explicitly search for something. I have had better success with managing my YouTube consumption after shifting to this tool. Settings inspired by Pinafore's wellness settings. @@ -71,27 +71,27 @@ I made this just for myself. The development is completely based on my needs and ## Installation Nim Coon depends on the following: -- youtube-dl +- yt-dlp - mpv (recommended) or vlc -- peerflix and webtorrent (for magnet links) +- webtorrent (for magnet links) Install MPV or VLC using your distribution's package manager. -Install YouTube-dl +Install yt-dlp ``` sh -pip3 install --user youtube-dl +pip3 install --user yt-dlp ``` -Install PeerFlix and WebTorrent +Install WebTorrent ```sh -npm install --global peerflix webtorrent-cli +npm install --global webtorrent-cli ``` (Optional) If you want your YouTube downloads to be faster, install `aria2` download manager. ### Installing using Nimble -NimCoon can be installed from Nimble repositories: +Nimcoon can be installed from Nimble repositories: ``` sh nimble install nimcoon @@ -144,7 +144,7 @@ again. ### Command line arguments -NimCoon provides both interactive and non-interactive arguments with significant +Nimcoon provides both interactive and non-interactive arguments with significant overlap. But some arguments might only be present in one mode. Non-interactive arguments are specified to the nimcoon program and apply @@ -159,7 +159,7 @@ case-by-case basis using the interactive arguments. | -d, --download | Download video or music | | -a, --auto-play | Play the next search result (YouTube only) | -Feel free to use these options in any combination. NimCoon will show a helpful +Feel free to use these options in any combination. Nimcoon will show a helpful error message if you pick incompatible options. Interactive arguments are provided during selection of a search result. These @@ -178,7 +178,7 @@ options as single characters. i.e | -d, --download | Download video or music | | -a, --auto-play | Play the next search result (YouTube only) | -Auto-playing videos leads to binge watching. The default option in NimCoon is to +Auto-playing videos leads to binge watching. The default option in Nimcoon is to support auto-play for music only. ## Development diff --git a/TODO.org b/TODO.org index ce4ef86..b6dbf20 100644 --- a/TODO.org +++ b/TODO.org @@ -16,3 +16,4 @@ - [ ] Better CLI using curses - select with arrows and press enter - illwill library can be used - see nim-mod project as an example +- [ ] Fix JSON parsing error thrown during search diff --git a/nimcoon.el b/nimcoon.el index 90f15e4..5f01750 100644 --- a/nimcoon.el +++ b/nimcoon.el @@ -7,24 +7,24 @@ ;;; Non-interactive functions to respond to URL clicks (defun nimcoon-play-url (url &rest args) - "Play given URL in NimCoon." + "Play given URL in Nimcoon." (start-process "nimcoon" nil "nimcoon" url)) -;; Play all YouTube URLs in NimCoon +;; Play all YouTube URLs in Nimcoon (setq browse-url-browser-function (quote (("youtu\\.?be" . nimcoon-play-url) ("." . browse-url-default-browser)))) (defun run-nimcoon(args query) - "Search by QUERY and play in NimCoon." + "Search by QUERY and play in Nimcoon." (call-process "nimcoon" nil 0 nil args query)) (defun nimcoon-search(args query) "Search by QUERY with the given ARGS." - (with-output-to-temp-buffer "*NimCoon search results*" - (call-process "nimcoon" nil "*NimCoon search results*" t args query) - (with-current-buffer "*NimCoon search results*" + (with-output-to-temp-buffer "*Nimcoon search results*" + (call-process "nimcoon" nil "*Nimcoon search results*" t args query) + (with-current-buffer "*Nimcoon search results*" (org-mode)))) ;;; Interactive functions @@ -44,9 +44,9 @@ (interactive "sSearch query: ") (run-nimcoon "-dlm" query)) -;; Assumes only one process exists. Must capture the pid of the running NimCoon process and only kill it. +;; Assumes only one process exists. Must capture the pid of the running Nimcoon process and only kill it. (defun nimcoon-kill-background-processes() - "Kill NimCoon process running in the background. Useful for stopping background music." + "Kill Nimcoon process running in the background. Useful for stopping background music." (interactive) (shell-command "kill `pgrep nimcoon` `pgrep mpv` `pgrep vlc`")) @@ -62,8 +62,8 @@ ;;; Keybindings (map! :leader - ;;; N --- NimCoon - (:prefix-map ("N" . "NimCoon") + ;;; N --- Nimcoon + (:prefix-map ("N" . "Nimcoon") (:prefix ("d" . "Download") :desc "Video" "v" #'nimcoon-download-video :desc "Music" "m" #'nimcoon-download-music) diff --git a/nimcoon.nimble b/nimcoon.nimble index e29c44c..92fc529 100644 --- a/nimcoon.nimble +++ b/nimcoon.nimble @@ -1,8 +1,8 @@ # Package -version = "0.8.3" +version = "0.9.0" author = "Joseph Nuthalapati" -description = "A command-line YouTube player and more" +description = "A command-line player for YouTube, PeerTube and more." license = "GPL-3.0" srcDir = "src" bin = @["nimcoon"] diff --git a/src/lib.nim b/src/lib.nim index 4dbbf8b..4064ae4 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -17,7 +17,7 @@ import let processOptions = {poStdErrToStdOut, poUsePath} # Add poEchoCmd to debug - PEERTUBE_REGEX = re"videos\/watch\/[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}" + PEERTUBE_REGEX = re"w\/[0-9a-zA-z]{22}" proc isInstalled(program: string): bool = @@ -82,14 +82,12 @@ proc play*(player: string, options: Table[string, bool], url: string, title: str proc directPlay*(url: string, player: string, options: Table[string, bool]) = let url = if find(url, PEERTUBE_REGEX) != -1 and "webtorrent".isInstalled: - getPeerTubeMagnetLink(url) + getPeerTubeMagnetLink(url, options["musicOnly"]) else: url if url.startswith("magnet:") or url.endswith(".torrent"): if options["musicOnly"]: - # TODO Replace with WebTorrent once it supports media player options - discard execShellCmd(&"peerflix '{url}' -a --{player} -- --no-video") + discard execShellCmd(&"webtorrent '{url}' --{player} --player-args='--no-video'") else: - # WebTorrent is so much faster! discard execProcess("webtorrent", args=[url, &"--{player}"], options=processOptions) else: play(player, options, url) @@ -119,24 +117,24 @@ func buildDownloadArgs(url: string, options: Options): seq[string] = proc download*(args: openArray[string], title: string) = printTitle("Downloading", title) - discard execShellCmd(&"youtube-dl {args.join(\" \")}") + discard execShellCmd(&"yt-dlp {args.join(\" \")}") proc directDownload*(url: string, options: Options) = let args = buildDownloadArgs(url, options) if "aria2c".isInstalled: - discard execShellCmd(&"youtube-dl {args.join(\" \")} --external-downloader aria2c --external-downloader-args '-x 16 -s 16 -k 2M'") + discard execShellCmd(&"yt-dlp {args.join(\" \")} --external-downloader aria2c --external-downloader-args '-x 16 -s 16 -k 2M'") else: - discard execShellCmd(&"youtube-dl {args.join(\" \")}") + discard execShellCmd(&"yt-dlp {args.join(\" \")}") proc luckyDownload*(searchQuery: string, options: Options) = - let args = @[&"ytsearch:\"{searchQuery}\""] & buildDownloadArgs("", options) - let title = execProcess(&"youtube-dl --get-title {args.join(\" \")}").split("\n")[0] + let args = @[&"ytsearch1:\"{searchQuery}\""] & buildDownloadArgs("", options) + let title = execProcess(&"yt-dlp --get-title {args.join(\" \")}").split("\n")[0] download(args, title) proc luckyPlay*(searchQuery: string, player: string, options: Options) = let args = @[&"ytsearch:\"{searchQuery}\""] & buildDownloadArgs("", options) - let output = execProcess(&"youtube-dl --get-url --get-title {args.join(\" \")}").split("\n") + let output = execProcess(&"yt-dlp --get-url --get-title {args.join(\" \")}").split("\n") let title = output[0] url = &"\"{output[1]}\"" diff --git a/src/nimcoon.nim b/src/nimcoon.nim index 1fd3ba6..9b3c6af 100644 --- a/src/nimcoon.nim +++ b/src/nimcoon.nim @@ -39,7 +39,7 @@ proc parseArguments(): CommandLineOptions = of cmdEnd: discard if searchQuery == "": - stderr.writeLine "NimCoon doesn't permit browsing. You must provide a search query." + stderr.writeLine "Nimcoon doesn't permit browsing. You must provide a search query." quit(1) (searchQuery, options) diff --git a/src/peertube.nim b/src/peertube.nim index 36f1054..16b6d23 100644 --- a/src/peertube.nim +++ b/src/peertube.nim @@ -5,14 +5,20 @@ import strformat, strutils -let PEERTUBE_REGEX = re"videos\/watch\/[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}" +let PEERTUBE_REGEX = re"w\/[0-9a-zA-z]{22}" -proc getPeerTubeMagnetLink*(url: string): string = +proc getPeerTubeMagnetLink*(url: string, musicOnly: bool): string = ## Gets the magnet link of the best possible resolution from PeerTube - let uuid = url.substr(find(url, PEERTUBE_REGEX) + "videos/watch/".len) + let uuid = url.substr(find(url, PEERTUBE_REGEX) + "w/".len) let domainName = url.substr(8, find(url, '/', start=8) - 1) let apiURL = &"https://{domainName}/api/v1/videos/{uuid}" let client = newHttpClient() let response = get(client, apiURL) let jsonNode = parseJson($response.body) - jsonNode["files"][0]["magnetUri"].getStr() + var files = jsonNode["files"] + if len(jsonNode["files"]) == 0: + files = jsonNode["streamingPlaylists"][0]["files"] + if musicOnly: + files[len(files)-1]["magnetUri"].getStr() + else: + files[0]["magnetUri"].getStr()