From aacdb1b5faf78b8de192197a77622985cb92eb9d Mon Sep 17 00:00:00 2001 From: Anthony Tesche Date: Thu, 19 Mar 2026 10:34:01 -0300 Subject: [PATCH 1/4] Add opensubtitles api for subtitles --- lobster.sh | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/lobster.sh b/lobster.sh index 50627b9..96d12aa 100755 --- a/lobster.sh +++ b/lobster.sh @@ -117,6 +117,8 @@ usage() { Use rofi instead of fzf -n, --no-subs Disable subtitles + -O, --opensubtitles + Search and select subtitles from OpenSubtitles.org (requires opensubtitles_api_key in config) -p, --provider Specify the provider to watch from (if no provider is provided, it defaults to Vidcloud) (currently supported: Vidcloud, UpCloud) -q, --quality @@ -169,8 +171,11 @@ configuration() { [ -z "$player" ] && player="mpv" [ -z "$download_dir" ] && download_dir="$PWD" [ -z "$provider" ] && provider="Vidcloud" - [ -z "$subs_language" ] && subs_language="english" + [ -z "$language" ] && language="pt-br" + [ -z "$subs_language" ] && subs_language="portuguese" subs_language="$(printf "%s" "$subs_language" | cut -c2-)" + [ -z "$opensubtitles_api_key" ] && opensubtitles_api_key="" + [ -z "$use_opensubtitles" ] && use_opensubtitles="false" [ -z "$histfile" ] && histfile="$data_dir/lobster_history.txt" && mkdir -p "$(dirname "$histfile")" [ -z "$history" ] && history=false [ -z "$use_external_menu" ] && use_external_menu="false" @@ -338,6 +343,7 @@ EOF image_link=$(printf "%s" "$choice" | cut -f1) media_id=$(printf "%s" "$choice" | cut -f2) media_type=$(printf "%s" "$choice" | cut -f3) + year=$(printf "%s" "$choice" | cut -f4 | $sed -nE "s@.*\[(.*)\]@\1@p") title=$(printf "%s" "$choice" | cut -f4 | $sed -nE "s@(.*) \[.*\]@\1@p") api_media_id=$(printf "%s" "$choice" | cut -f5) fi @@ -607,6 +613,59 @@ EOF fi } + choose_opensubtitles() { + if [ -z "$opensubtitles_api_key" ]; then + send_notification "Set opensubtitles_api_key in config to use OpenSubtitles" + return 1 + fi + send_notification "Searching OpenSubtitles..." + encoded_query=$(printf "%s" "$title" | $sed 's/ /%20/g; s/:/%3A/g; s/\//%2F/g') + send_notification "Searching OpenSubtitles for \"$title\" with language \"$language\"..." + json=$(curl -s -L --request GET --url "https://api.opensubtitles.com/api/v1/subtitles?type=${media_type}&query=${encoded_query}&languages=${language}&year=${year}" -A "lobster" -H "Api-Key: ${opensubtitles_api_key}" -H "Accept: application/json") + + entries=$(printf "%s" "$json" | tr -d '\n' | \ + $sed 's/\[{"id"/\n{"id"/g; s/},{"id"/\n{"id"/g' | \ + while IFS= read -r record; do + file_id=$(printf "%s" "$record" | $sed -nE 's/.*"file_id":([0-9]+).*/\1/p' | head -1) + language=$(printf "%s" "$record" | $sed -nE 's/.*"language":"([^"]+)".*/\1/p' | head -1) + release=$(printf "%s" "$record" | $sed -nE 's/.*"release":"([^"]+)".*/\1/p' | head -1) + downloads=$(printf "%s" "$record" | $sed -nE 's/.*"download_count":([0-9]+).*/\1/p' | head -1) + [ -z "$downloads" ] && downloads="?" + [ -n "$file_id" ] && [ -n "$language" ] && \ + printf "%s\t[%s] %s (%s downloads)\n" "$file_id" "$language" "$release" "$downloads" + done) + + [ -z "$entries" ] && send_notification "No subtitles found on OpenSubtitles" && return 1 + + chosen=$(printf "%s" "$entries" | launcher "Select subtitle from OpenSubtitles: " "2") + [ $? -ne 0 ] && return 1 + [ -z "$chosen" ] && return 1 + + file_id=$(printf "%s" "$chosen" | cut -f1) + [ -z "$file_id" ] && return 1 + + dl_response=$(curl -s -X POST "https://api.opensubtitles.com/api/v1/download" \ + -H "Api-Key: ${opensubtitles_api_key}" \ + -H "User-Agent: lobster v${LOBSTER_VERSION}" \ + -H "Content-Type: application/json" \ + -d "{\"file_id\": ${file_id}}") + + link=$(printf "%s" "$dl_response" | $sed -nE 's/.*"link":"([^"]+)".*/\1/p') + [ -z "$link" ] && send_notification "Failed to get subtitle link from OpenSubtitles" && return 1 + + sub_file="$tmp_dir/opensubtitles_${file_id}.srt" + curl -s -L "$link" -o "$sub_file" -H "User-Agent: lobster v${LOBSTER_VERSION}" + + if [ -f "$sub_file" ]; then + subs_arg="--sub-file" + subs_links="$sub_file" + send_notification "Subtitle loaded from OpenSubtitles" + else + send_notification "Failed to download subtitle from OpenSubtitles" + return 1 + fi + } + check_history() { if [ ! -f "$histfile" ]; then [ "$image_preview" = "true" ] && send_notification "Now Playing" "5000" "$images_cache_dir/ $title ($media_type) $media_id.jpg" "$title" @@ -899,7 +958,7 @@ EOF ffmpeg_meta="" ffmpeg_maps="" - if [ "$no_subs" = "true" ]; then + if [ "$no_subs" = "true" || "$use_opensubtitles" = "false" ]; then # no subtitles sub_ops="" else @@ -940,6 +999,7 @@ EOF [ -z "$embed_link" ] && exit 1 extract_from_embed [ -z "$video_link" ] && exit 1 + [ "$use_opensubtitles" = "true" ] && [ "$no_subs" != "true" ] && choose_opensubtitles if [ "$download" = "true" ]; then if [ "$media_type" = "movie" ]; then if [ "$image_preview" = "true" ]; then @@ -1144,6 +1204,9 @@ EOF -n | --no-subs) no_subs="true" && shift ;; + -O | --opensubtitles) + use_opensubtitles="true" && shift + ;; *) if [ "${1#-}" != "$1" ]; then query="$query $1" From 4b68c03cb2956dde5463b3bc39ea95585ea78730 Mon Sep 17 00:00:00 2001 From: Anthony Tesche Date: Thu, 19 Mar 2026 10:42:27 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=C3=BCpdate=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index b8e1de1..522e8d7 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,10 @@ Options: Specify the subtitle language (if no language is provided, it defaults to english) --rofi, --external-menu Use rofi instead of fzf + -n, --no-subs + Disable subtitles + -O, --opensubtitles + Search and select subtitles from OpenSubtitles.org (requires opensubtitles_api_key in config) -p, --provider Specify the provider to watch from (if no provider is provided, it defaults to Vidcloud) (currently supported: Vidcloud, UpCloud) -q, --quality @@ -541,6 +545,20 @@ Example use case: lobster -n ``` +### `-O` / `--opensubtitles` argument +Flag: Use -O or --opensubtitles when launching lobster, or set use_opensubtitles="true" in your config file. +After selecting a movie/episode and getting the video link, lobster searches OpenSubtitles.com for subtitles +using the movie title. A fzf/rofi selection appears showing each result as: +[en] Movie.Title.2021.1080p.BluRay (5000 downloads) +Download: The selected subtitle is downloaded to the temp dir and passed to the player via --sub-file. + +``` +Setup required — you need a free API key from https://www.opensubtitles.com/consumers. Add it to your config +(~/.config/lobster/lobster_config.sh): +opensubtitles_api_key="your_key_here" use_opensubtitles="true" # optional, or use -O flag +``` +The free tier allows 5 subtitle downloads/day. Searching has no limit. + ### `-r` / `--recent` `` argument By passing this argument, you can see watch most recently released movies and TV From 679a11c7f0f557bd5646ec2eafce9b6c89263de2 Mon Sep 17 00:00:00 2001 From: Anthony Tesche Date: Thu, 19 Mar 2026 10:52:54 -0300 Subject: [PATCH 3/4] Shellcheck fix --- lobster.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lobster.sh b/lobster.sh index 96d12aa..8076194 100755 --- a/lobster.sh +++ b/lobster.sh @@ -958,7 +958,7 @@ EOF ffmpeg_meta="" ffmpeg_maps="" - if [ "$no_subs" = "true" || "$use_opensubtitles" = "false" ]; then + if [ "$no_subs" = "true" ] || [ "$use_opensubtitles" = "false" ]; then # no subtitles sub_ops="" else From b715145e7742ad8f391f58b22aef86e59cd15698 Mon Sep 17 00:00:00 2001 From: Anthony Tesche Date: Thu, 19 Mar 2026 10:56:40 -0300 Subject: [PATCH 4/4] shfmt fix --- lobster.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lobster.sh b/lobster.sh index 8076194..ffeca74 100755 --- a/lobster.sh +++ b/lobster.sh @@ -622,16 +622,16 @@ EOF encoded_query=$(printf "%s" "$title" | $sed 's/ /%20/g; s/:/%3A/g; s/\//%2F/g') send_notification "Searching OpenSubtitles for \"$title\" with language \"$language\"..." json=$(curl -s -L --request GET --url "https://api.opensubtitles.com/api/v1/subtitles?type=${media_type}&query=${encoded_query}&languages=${language}&year=${year}" -A "lobster" -H "Api-Key: ${opensubtitles_api_key}" -H "Accept: application/json") - - entries=$(printf "%s" "$json" | tr -d '\n' | \ - $sed 's/\[{"id"/\n{"id"/g; s/},{"id"/\n{"id"/g' | \ + + entries=$(printf "%s" "$json" | tr -d '\n' | + $sed 's/\[{"id"/\n{"id"/g; s/},{"id"/\n{"id"/g' | while IFS= read -r record; do file_id=$(printf "%s" "$record" | $sed -nE 's/.*"file_id":([0-9]+).*/\1/p' | head -1) language=$(printf "%s" "$record" | $sed -nE 's/.*"language":"([^"]+)".*/\1/p' | head -1) release=$(printf "%s" "$record" | $sed -nE 's/.*"release":"([^"]+)".*/\1/p' | head -1) downloads=$(printf "%s" "$record" | $sed -nE 's/.*"download_count":([0-9]+).*/\1/p' | head -1) [ -z "$downloads" ] && downloads="?" - [ -n "$file_id" ] && [ -n "$language" ] && \ + [ -n "$file_id" ] && [ -n "$language" ] && printf "%s\t[%s] %s (%s downloads)\n" "$file_id" "$language" "$release" "$downloads" done) @@ -1233,4 +1233,4 @@ EOF main } 2>&1 | tee "$lobster_logfile" >&3 2>&4 -exec 1>&3 2>&4 +exec 1>&3 2>&4 \ No newline at end of file