### Alternative installation methods
* [Snap Store](https://snapcraft.io/video-downloader)
* [Fedora](https://src.fedoraproject.org/rpms/video-downloader): `sudo dnf install video-downloader`
* [Arch User Repository](https://aur.archlinux.org/packages/video-downloader)
## Translation
We use [Weblate](https://hosted.weblate.org/engage/video-downloader/) to translate the UI, so feel free to contribute translations over there.
## Screenshots



## Hidden configuration options
The behavior of the program can be tweaked with GSettings.
### Automatic Subtitles
List of additional automatic subtitles to download. The entry `all` matches all languages.
The default is `[]`.
#### Flatpak
```
flatpak run --command=gsettings com.github.unrud.VideoDownloader set com.github.unrud.VideoDownloader automatic-subtitles "['de','en']"
```
#### Snap
```
snap run --shell video-downloader -c 'gsettings "$@"' '' set com.github.unrud.VideoDownloader automatic-subtitles "['de','en']"
```
## Debug
To display messages from **yt-dlp** run program with the environment variable `G_MESSAGES_DEBUG=yt-dlp`.
To display information about GOBject references, start the program with the environment variable `G_MESSAGES_DEBUG=gobject-ref`.
video-downloader-0.12.22/build-aux/ 0000775 0000000 0000000 00000000000 14741312404 0017012 5 ustar 00root root 0000000 0000000 video-downloader-0.12.22/build-aux/meson/ 0000775 0000000 0000000 00000000000 14741312404 0020133 5 ustar 00root root 0000000 0000000 video-downloader-0.12.22/build-aux/meson/create-gresource.py 0000664 0000000 0000000 00000001570 14741312404 0023747 0 ustar 00root root 0000000 0000000 import contextlib
import os
import sys
import xml.etree.ElementTree as ET
base_dirs = [
os.path.join(os.environ['MESON_SOURCE_ROOT'], os.environ['MESON_SUBDIR']),
os.path.join(os.environ['MESON_BUILD_ROOT'], os.environ['MESON_SUBDIR']),
]
_, prefix, *paths = sys.argv
xml = ET.ElementTree()
root_element = ET.Element('gresources')
xml._setroot(root_element)
resource_element = ET.Element('gresource')
root_element.append(resource_element)
resource_element.set('prefix', prefix)
for path in paths:
alias = path
for base_dir in base_dirs:
with contextlib.suppress(ValueError):
alias = min(alias, os.path.relpath(path, base_dir), key=len)
file_element = ET.Element('file')
resource_element.append(file_element)
file_element.set('alias', alias)
file_element.text = path
xml.write(sys.stdout.buffer, encoding='utf-8', xml_declaration=True)
video-downloader-0.12.22/build-aux/meson/extract-xml.py 0000664 0000000 0000000 00000001300 14741312404 0022747 0 ustar 00root root 0000000 0000000 import io
import sys
import xml.etree.ElementTree as ET
from xml.sax import saxutils
class CommentTreeBuilder(ET.TreeBuilder):
def comment(self, data):
self.start(ET.Comment, {})
self.data(data)
self.end(ET.Comment)
def make_xml_parser():
return ET.XMLParser(target=CommentTreeBuilder())
_, *flags, xml_path, search_xpath = sys.argv
xml = ET.parse(xml_path, parser=make_xml_parser())
for element in xml.findall(search_xpath):
xml._setroot(element)
f = io.StringIO()
xml.write(f, encoding='unicode')
xml_text = f.getvalue()
if '--escape' in flags:
xml_text = saxutils.escape(xml_text)
sys.stdout.buffer.write(xml_text.encode('utf-8'))
video-downloader-0.12.22/build-aux/meson/merge-xml.py 0000664 0000000 0000000 00000001133 14741312404 0022400 0 ustar 00root root 0000000 0000000 import sys
import xml.etree.ElementTree as ET
class CommentTreeBuilder(ET.TreeBuilder):
def comment(self, data):
self.start(ET.Comment, {})
self.data(data)
self.end(ET.Comment)
def make_xml_parser():
return ET.XMLParser(target=CommentTreeBuilder())
_, main_xml_path, insert_xml_path, insert_xpath = sys.argv
main_xml = ET.parse(main_xml_path, parser=make_xml_parser())
insert_xml = ET.parse(insert_xml_path, parser=make_xml_parser())
main_xml.find(insert_xpath).append(insert_xml.getroot())
main_xml.write(sys.stdout.buffer, encoding='utf-8', xml_declaration=True)
video-downloader-0.12.22/build-aux/meson/move.py 0000664 0000000 0000000 00000000362 14741312404 0021454 0 ustar 00root root 0000000 0000000 from os import environ, path, sys
from shutil import move
destdir = environ.get('DESTDIR', '')
prefix = environ['MESON_INSTALL_PREFIX']
source, dest = sys.argv[1:]
move(destdir + path.join(prefix, source), destdir + path.join(prefix, dest))
video-downloader-0.12.22/com.github.unrud.VideoDownloader.json 0000664 0000000 0000000 00000014742 14741312404 0024302 0 ustar 00root root 0000000 0000000 {
"app-id": "com.github.unrud.VideoDownloader",
"runtime": "org.gnome.Platform",
"runtime-version": "47",
"sdk": "org.gnome.Sdk",
"command": "video-downloader",
"finish-args": [
"--share=network",
"--share=ipc",
"--socket=fallback-x11",
"--device=dri",
"--socket=wayland",
"--filesystem=xdg-download/VideoDownloader:create"
],
"cleanup": [
"/include",
"/lib/pkgconfig",
"/man",
"/share/doc",
"/share/gtk-doc",
"/share/man",
"/share/pkgconfig",
"*.la",
"*.a"
],
"cleanup-commands": [
"mkdir -p /app/lib/ffmpeg"
],
"add-extensions": {
"org.freedesktop.Platform.ffmpeg-full": {
"directory": "lib/ffmpeg",
"version": "24.08",
"add-ld-path": "."
}
},
"modules": [
{
"name": "pyxattr",
"buildsystem": "simple",
"build-commands": [
"pip3 install --prefix=/app ."
],
"sources": [
{
"type": "archive",
"url": "https://github.com/iustin/pyxattr/archive/refs/tags/v0.8.1.tar.gz",
"sha256": "ce7ef783e751b96610a6eb32fc49a89340b5dc575fbe15054ce7935ebaf49edb",
"x-checker-data": {
"type": "json",
"url": "https://api.github.com/repos/iustin/pyxattr/releases/latest",
"version-query": ".tag_name",
"url-query": "\"https://github.com/iustin/pyxattr/archive/refs/tags/\" + $version + \".tar.gz\""
}
}
]
},
{
"name": "mutagen",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-build-isolation --prefix=/app ."
],
"sources": [
{
"type": "archive",
"url": "https://github.com/quodlibet/mutagen/archive/refs/tags/release-1.47.0.tar.gz",
"sha256": "f7489e19d375c31ba1962ab19e11eca8b9f86f05bfd99cef467f8dd875d8941e",
"x-checker-data": {
"type": "json",
"url": "https://api.github.com/repos/quodlibet/mutagen/releases/latest",
"version-query": ".tag_name",
"url-query": "\"https://github.com/quodlibet/mutagen/archive/refs/tags/\" + $version + \".tar.gz\""
}
}
]
},
{
"name": "pycryptodomex",
"buildsystem": "simple",
"build-commands": [
"touch .separate_namespace",
"pip3 install --no-build-isolation --prefix=/app ."
],
"sources": [
{
"type": "archive",
"url": "https://github.com/Legrandin/pycryptodome/archive/refs/tags/v3.21.0.tar.gz",
"sha256": "195e5cdfbb550b03f83f2af2aa4652c14b64783574d835fe61bb06c8fc06ba21",
"x-checker-data": {
"type": "json",
"url": "https://api.github.com/repos/Legrandin/pycryptodome/tags",
"version-query": "[.[].name | select(test(\"^v?[0-9.]+$\"))] | sort_by(sub(\"^v\"; \"\") | split(\".\") | map(tonumber))[-1]",
"url-query": "\"https://github.com/Legrandin/pycryptodome/archive/refs/tags/\" + $version + \".tar.gz\""
}
}
]
},
{
"name": "websockets",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-build-isolation --prefix=/app ."
],
"sources": [
{
"type": "archive",
"url": "https://github.com/aaugustin/websockets/archive/refs/tags/14.1.tar.gz",
"sha256": "822f3c2bd7ac6b2d9b90271dccaf4e74453b3b0aba5323ade0bcade60102a5c1",
"x-checker-data": {
"type": "json",
"url": "https://api.github.com/repos/aaugustin/websockets/tags",
"version-query": "[.[].name | select(test(\"^v?[0-9.]+$\"))] | sort_by(sub(\"^v\"; \"\") | split(\".\") | map(tonumber))[-1]",
"url-query": "\"https://github.com/aaugustin/websockets/archive/refs/tags/\" + $version + \".tar.gz\""
}
}
]
},
{
"name": "brotli",
"buildsystem": "simple",
"build-commands": [
"pip3 install --prefix=/app ."
],
"sources": [
{
"type": "archive",
"url": "https://github.com/google/brotli/archive/refs/tags/v1.1.0.tar.gz",
"sha256": "e720a6ca29428b803f4ad165371771f5398faba397edf6778837a18599ea13ff",
"x-checker-data": {
"type": "json",
"url": "https://api.github.com/repos/google/brotli/releases/latest",
"version-query": ".tag_name",
"url-query": "\"https://github.com/google/brotli/archive/refs/tags/\" + $version + \".tar.gz\""
}
}
]
},
{
"name": "yt-dlp",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-dependencies --prefix=/app \"$(echo *.whl)[default]\""
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/f3/9d/782c67465798478b3f8cf8c72da771e1eb0956e13b820f862b35de66d4a7/yt_dlp-2025.1.12-py3-none-any.whl",
"sha256": "f7ea19afb64f8e457a1b9598ddb67f8deaa313bf1d57abd5612db9272ab10795",
"x-checker-data": {
"type": "pypi",
"name": "yt-dlp",
"packagetype": "bdist_wheel"
}
}
]
},
{
"name": "video-downloader",
"builddir": true,
"buildsystem": "meson",
"sources": [
{
"type": "git",
"path": "."
}
]
}
]
}
video-downloader-0.12.22/data/ 0000775 0000000 0000000 00000000000 14741312404 0016031 5 ustar 00root root 0000000 0000000 video-downloader-0.12.22/data/com.github.unrud.VideoDownloader-symbolic.svg 0000664 0000000 0000000 00000001236 14741312404 0026652 0 ustar 00root root 0000000 0000000
video-downloader-0.12.22/data/com.github.unrud.VideoDownloader.Source.svg 0000664 0000000 0000000 00000065363 14741312404 0026305 0 ustar 00root root 0000000 0000000
video-downloader-0.12.22/data/com.github.unrud.VideoDownloader.desktop.in 0000664 0000000 0000000 00000000746 14741312404 0026317 0 ustar 00root root 0000000 0000000 [Desktop Entry]
Name=Video Downloader
Comment=Download web videos
Exec=video-downloader
Icon=com.github.unrud.VideoDownloader
Terminal=false
Type=Application
Categories=Network;GTK;
StartupNotify=true
X-GNOME-UsesNotifications=true
Actions=new-window;
# TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
Keywords=YouTube;Download;
[Desktop Action new-window]
Name=New Window
Exec=video-downloader
video-downloader-0.12.22/data/com.github.unrud.VideoDownloader.gschema.xml 0000664 0000000 0000000 00000001334 14741312404 0026441 0 ustar 00root root 0000000 0000000
Fix format selection for extractors that provide either video width or height.
Stop downloader in case of error.
Fix link to download folder.
Remember last settings and switch to GTK.
Adjust menu colors to theme.
Fix crash with non-integer X DPI.
Move AppData to metainfo.
Download all videos in playlist.
Set window icon.
Make window resizeable and fix font sizes.
Stop progress bar jumping around.
Support videos with emoticons in the title.
Initial release.
Download videos from websites with an easy-to-use interface. Provides the following features:
Based on yt-dlp.