commit ec197d8d5e5064de686f819f7532f7b7ad6bb1e5 Author: Bernd Date: Wed Jan 15 22:48:25 2025 +0500 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..f8e5aaa --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# MPV Subtitle Translator (SubTranslate) + +A simple [mpv](https://mpv.io/) Lua script that uses Google Translate API calls to translate currently displayed subtitles on-the-fly. + +## Features + +- **Auto-detects** the source language (via `source_lang = 'auto'`). +- Translates **into Russian** by default (change the `source_lang = 'ru'` parameter to any [Google Translate language code](https://cloud.google.com/translate/docs/languages)). +- Displays the translation in mpv’s On-Screen Display (OSD) for a selected duration (select in options). + +## Requirements + +- **mpv** (tested on versions 0.29+; works with older versions if you use the custom `url_encode()` script). +- **curl** (the script uses `mp.utils.subprocess` to invoke `curl`). + +> **Note:** This script uses an **unofficial** Google Translate endpoint. Google can change or block this endpoint without notice. + +## Installation + +1. **Download** or create the script file: [SubTranslate.lua](./SubTranslate.lua). +2. **Place** it in your mpv `scripts` folder: + - **Linux/macOS**: `~/.config/mpv/scripts/` + - **Windows**: `%APPDATA%\mpv\scripts\` +3. **Restart** mpv (or open a new instance) so that the script loads. + +## Usage + +1. **Open** a video with subtitles in mpv. +2. When you see a subtitle on-screen, press **Ctrl+T** (you can change this keybind in the options at the beginning of the script). +3. The script sends the subtitle text to Google Translate, retrieves the translation, and displays it in the OSD. + +## Changing the Target Language + +- Edit the `SubTranslate.lua` file. +- Look for `destination_lang = 'ru'` and change it to whatever language you want to translate + +## Troubleshooting + +1. **`attempt to call field 'encode_url' (a nil value)`** + - Your mpv version might be too old to include `utils.encode_url()`. Try using the script version that defines a custom `url_encode()` function, or upgrade mpv to a more recent release. + +2. **Translation Fails or Outputs Unexpected Results** + - Make sure you have a working internet connection. + - Check that `curl` is installed and in your system path. + - The unofficial Google Translate endpoint might be down or blocked. + +3. **Other Issues** + - Run mpv from a terminal to see if there are any error messages. diff --git a/SubTranslate.lua b/SubTranslate.lua new file mode 100644 index 0000000..bb1d0e4 --- /dev/null +++ b/SubTranslate.lua @@ -0,0 +1,68 @@ +-- Options +local o = { + source_lang = 'en', -- Translate from, e.g. 'ru', 'en', 'de', etc. Change to 'auto' to detect the source language + destination_lang = 'ru', -- Translate to + duration = 10, -- how long will the translation be shown on the OSD screen (in secs.) + key_binding = "ctrl+t" -- Keybind for translating the current sub +} + +local mp = require 'mp' +local utils = require 'mp.utils' + +-- Custom URL-encode function (Lua 5.1+) +local function url_encode(str) + if not str then return "" end + -- Convert line breaks to spaces, trim leading/trailing whitespace + str = str:gsub("\n", " "):gsub("^%s*(.-)%s*$", "%1") + -- Percent-encode special characters + str = str:gsub("([^%w _%%%-%.~])", function(char) + return string.format("%%%02X", string.byte(char)) + end) + -- Replace spaces with %20 + str = str:gsub(" ", "%%20") + return str +end + +local function translate_subtitle() + -- Get the current subtitle text + local text = mp.get_property("sub-text") + if not text or text == "" then + mp.osd_message("No subtitles to translate.") + return + end + + -- Encode text for URL + local encodedText = url_encode(text) + + -- Google Translate API endpoint + local url = string.format( + "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" .. o.source_lang .. "&tl=" .. o.destination_lang .. "&dt=t&q=%s", + encodedText + ) + + -- Use curl to fetch the translation result + local res = utils.subprocess({ + args = {"curl", "-s", url}, + cancellable = false + }) + + if res.status ~= 0 or not res.stdout or res.stdout == "" then + mp.osd_message("Translation request failed.") + return + end + + -- Parse the JSON returned by Google Translate + local data = utils.parse_json(res.stdout) + if not data or not data[1] or not data[1][1] or not data[1][1][1] then + mp.osd_message("Failed to parse translation.") + return + end + + -- Extract the translated text + local translation = data[1][1][1] + + mp.osd_message("Translation:\n" .. translation, o.duration) +end + +-- Bind the function to a hotkey, e.g. Ctrl+T +mp.add_key_binding(o.key_binding, "translate_subtitle", translate_subtitle)