{"id":13478828,"url":"https://github.com/meeb/tubesync","last_synced_at":"2025-05-14T04:07:39.856Z","repository":{"id":37403623,"uuid":"314975143","full_name":"meeb/tubesync","owner":"meeb","description":"Syncs YouTube channels and playlists to a locally hosted media server","archived":false,"fork":false,"pushed_at":"2025-05-12T05:45:23.000Z","size":7087,"stargazers_count":2271,"open_issues_count":96,"forks_count":135,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-05-12T06:35:39.464Z","etag":null,"topics":["media-server","plex","pvr","tubesync","youtube","youtube-dl"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/meeb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["meeb"]}},"created_at":"2020-11-22T06:33:42.000Z","updated_at":"2025-05-12T05:45:27.000Z","dependencies_parsed_at":"2022-07-08T18:00:56.165Z","dependency_job_id":"2f561204-53cf-4e18-9e1e-e331a059ea97","html_url":"https://github.com/meeb/tubesync","commit_stats":{"total_commits":641,"total_committers":37,"mean_commits":"17.324324324324323","dds":"0.34009360374414976","last_synced_commit":"e2f2a7bb49c474aeb4df0727327b75150e0ea4f4"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meeb%2Ftubesync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meeb%2Ftubesync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meeb%2Ftubesync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/meeb%2Ftubesync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/meeb","download_url":"https://codeload.github.com/meeb/tubesync/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069220,"owners_count":22009513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["media-server","plex","pvr","tubesync","youtube","youtube-dl"],"created_at":"2024-07-31T16:02:04.060Z","updated_at":"2025-05-14T04:07:39.834Z","avatar_url":"https://github.com/meeb.png","language":"Python","funding_links":["https://github.com/sponsors/meeb"],"categories":["Python","Install from Source","others","Overview","Software"],"sub_categories":["Media Server","YouTube","Media Management","Automation"],"readme":"# TubeSync\n\n**This is a preview release of TubeSync, it may contain bugs but should be usable**\n\nTubeSync is a PVR (personal video recorder) for YouTube. Or, like Sonarr but for\nYouTube (with a built-in download client). It is designed to synchronize channels and\nplaylists from YouTube to local directories and update your media server once media is\ndownloaded.\n\nIf you want to watch YouTube videos in particular quality or settings from your local\nmedia server, then TubeSync is for you. Internally, TubeSync is a web interface wrapper\non `yt-dlp` and `ffmpeg` with a task scheduler.\n\nThere are several other web interfaces to YouTube and `yt-dlp` all with varying\nfeatures and implementations. TubeSync's largest difference is full PVR experience of\nupdating media servers and better selection of media formats. Additionally, to be as\nhands-free as possible, TubeSync has gradual retrying of failures with back-off timers\nso media which fails to download will be retried for an extended period making it,\nhopefully, quite reliable.\n\n\n# Latest container image\n\n```yaml\nghcr.io/meeb/tubesync:latest\n```\n\n# Screenshots\n\n### Dashboard\n\n![TubeSync Dashboard](https://github.com/meeb/tubesync/blob/main/docs/dashboard-v0.5.png?raw=true)\n\n### Sources overview\n\n![TubeSync sources overview](https://github.com/meeb/tubesync/blob/main/docs/sources-v0.5.png?raw=true)\n\n### Source details\n\n![TubeSync source details](https://github.com/meeb/tubesync/blob/main/docs/source-v0.5.png?raw=true)\n\n### Media overview\n\n![TubeSync media overview](https://github.com/meeb/tubesync/blob/main/docs/media-v0.5.png?raw=true)\n\n### Media details\n\n![TubeSync media-details](https://github.com/meeb/tubesync/blob/main/docs/media-item-v0.5.png?raw=true)\n\n\n# Requirements\n\nFor the easiest installation, you will need an environment to run containers such as\nDocker or Podman. You will also need as much space as you want to allocate to\ndownloaded media and thumbnails. If you download a lot of media at high resolutions\nthis can be very large.\n\n\n# What to expect\n\nOnce running, TubeSync will download media to a specified directory. Inside this\ndirectory will be a `video` and `audio` subdirectories. All media which only has an\naudio stream (such as music) will download to the `audio` directory. All media with a\nvideo stream will be downloaded to the `video` directory. All administration of\nTubeSync is performed via a web interface. You can optionally add a media server,\ncurrently only Jellyfin or Plex, to complete the PVR experience.\n\n\n# Installation\n\nTubeSync is designed to be run in a container, such as via Docker or Podman. It also\nworks in a Docker Compose stack. `amd64` (most desktop PCs and servers) and `arm64`\n(modern ARM computers, such as the Raspberry Pi 3 or later) are supported.\n\nExample (with Docker on *nix):\n\nFirst find the user ID and group ID you want to run TubeSync as, if you're not\nsure what this is it's probably your current user ID and group ID:\n\n```bash\n$ id\n# Example output, in this example, user ID = 1000, group ID = 1000\n# id uid=1000(username) gid=1000(username) groups=1000(username),129(docker)\n```\n\nYou can find your local timezone name here:\n\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones\n\nIf unset, `TZ` defaults to `UTC`.\n\nNext, create the directories you're going to use for config data and downloads:\n\n```bash\n$ mkdir /some/directory/tubesync-config\n$ mkdir /some/directory/tubesync-downloads\n```\n\nFinally, download and run the container:\n\n```bash\n# Pull image\n$ docker pull ghcr.io/meeb/tubesync:latest\n# Start the container using your user ID and group ID\n$ docker run \\\n  -d \\\n  --name tubesync \\\n  -e PUID=1000 \\\n  -e PGID=1000 \\\n  -e TZ=Europe/London \\\n  -v /some/directory/tubesync-config:/config \\\n  -v /some/directory/tubesync-downloads:/downloads \\\n  -p 4848:4848 \\\n  ghcr.io/meeb/tubesync:latest\n```\n\nOnce running, open `http://localhost:4848` in your browser and you should see the\nTubeSync dashboard. If you do, you can proceed to adding some sources (YouTube channels\nand playlists). If not, check `docker logs tubesync` to see what errors might be\noccurring, typical ones are file permission issues.\n\nAlternatively, for Docker Compose, you can use something like:\n\n```yml\nservices:\n  tubesync:\n    image: ghcr.io/meeb/tubesync:latest\n    container_name: tubesync\n    restart: unless-stopped\n    ports:\n      - 4848:4848\n    volumes:\n      - /some/directory/tubesync-config:/config\n      - /some/directory/tubesync-downloads:/downloads\n    environment:\n      - TZ=Europe/London\n      - PUID=1000\n      - PGID=1000\n```\n\n\u003e [!IMPORTANT]  \n\u003e If the `/downloads` directory is mounted from a [Samba volume](https://docs.docker.com/engine/storage/volumes/#create-cifssamba-volumes), be sure to also supply the `uid` and `gid` mount parameters in the driver options.\n\u003e These must be matched to the `PUID` and `PGID` values, which were specified as environment variables.\n\u003e \n\u003e Matching these user and group ID numbers prevents issues when executing file actions, such as writing metadata. See [this issue](https://github.com/meeb/tubesync/issues/616#issuecomment-2593458282) for details.\n\n## Optional authentication\n\nAvailable in `v1.0` (or `:latest`)and later. If you want to enable a basic username and\npassword to be required to access the TubeSync dashboard you can set them with the\nfollowing environment variables:\n\n```bash\nHTTP_USER\nHTTP_PASS\n```\n\nFor example, in the `docker run ...` line add in:\n\n```bash\n...\n-e HTTP_USER=some-username \\\n-e HTTP_PASS=some-secure-password \\\n...\n```\n\nOr in your Docker Compose file you would add in:\n\n```yaml\n...\n    environment:\n      - HTTP_USER=some-username\n      - HTTP_PASS=some-secure-password\n...\n```\n\nWhen BOTH `HTTP_USER` and `HTTP_PASS` are set then basic HTTP authentication will be\nenabled.\n\n\n# Updating\n\nTo update, you can just pull a new version of the container image as they are released.\n\n```bash\n$ docker pull ghcr.io/meeb/tubesync:v[number]\n```\n\nBack-end updates such as database migrations should be automatic.\n\n\n# Moving, backing up, etc.\n\nTubeSync, when running in its default container, stores thumbnails, cache and its\nSQLite database into the `/config` directory and wherever you've mapped that to on your\nfile system. Just copying or moving this directory and making sure the permissions are\ncorrect is sufficient to move, back up or migrate your TubeSync install.\n\n\n# Using TubeSync\n\n### 1. Add some sources\n\nPick your favourite YouTube channels or playlists, pop over to the \"sources\" tab, click\nwhichever add button suits you, enter the URL and validate it. This process extracts\nthe key information from the URL and makes sure it's a valid URL. This is the channel\nname for YouTube channels and the playlist ID for YouTube playlists.\n\nYou will then be presented with the initial add a source form where you can select\nall the features you want, such as how often you want to index your source and the\nquality of the media you want to download. Once happy, click \"add source\".\n\n\n### 2. Wait\n\nThat's about it. All other actions are automatic and performed on timers by scheduled\ntasks. You can see what your TubeSync instance is doing on the \"tasks\" tab.\n\nAs media is indexed and downloaded it will appear in the \"media\" tab.\n\n\n### 3. Media Server updating\n\nCurrently TubeSync supports Plex and Jellyfin as media servers. You can add your local Jellyfin or Plex server\nunder the \"media servers\" tab.\n\n\n# Logging and debugging\n\nTubeSync outputs useful logs, errors and debugging information to the console. You can\nview these with:\n\n```bash\n$ docker logs --follow tubesync\n```\n\nTo include logs with an issue report, please exteact a file and attach it to the issue.\nThe command below creates the `TubeSync.logs.txt` file with the logs from the `tubesync` container:\n\n```bash\ndocker logs -t tubesync \u003e TubeSync.logs.txt 2\u003e\u00261\n```\n\n\n# Advanced usage guides\n\nOnce you're happy using TubeSync there are some advanced usage guides for more complex\nand less common features:\n\n * [Import existing media into TubeSync](https://github.com/meeb/tubesync/blob/main/docs/import-existing-media.md)\n * [Sync or create missing metadata files](https://github.com/meeb/tubesync/blob/main/docs/create-missing-metadata.md)\n * [Reset tasks from the command line](https://github.com/meeb/tubesync/blob/main/docs/reset-tasks.md)\n * [Using PostgreSQL, MySQL or MariaDB as database backends](https://github.com/meeb/tubesync/blob/main/docs/other-database-backends.md)\n * [Using cookies](https://github.com/meeb/tubesync/blob/main/docs/using-cookies.md)\n * [Reset metadata](https://github.com/meeb/tubesync/blob/main/docs/reset-metadata.md)\n\n\n# Warnings\n\n### 1. Automated file renaming\n\u003e [!IMPORTANT]\n\u003e Currently, file renaming is not enabled by default.\n\u003e Enabling this feature by default is planned in an upcoming release, after `2025-006-01`.\n\u003e \n\u003e To prevent your installation from scheduling media file renaming tasks,\n\u003e you must set [`TUBESYNC_RENAME_ALL_SOURCES=False`](#advanced-configuration) in the environment variables or `RENAME_ALL_SOURCES = False` in [`settings.py`](../1fc0462c11741621350053144ab19cba5f266cb2/tubesync/tubesync/settings.py#L183).\n\n### 2. Index frequency\n\nIt's a good idea to add sources with as long of an index frequency as possible. This is\nthe duration between indexes of the source. An index is when TubeSync checks to see\nwhat videos available on a channel or playlist to find new media. Try and keep this as\nlong as possible, up to 24 hours.\n\n\n### 3. Indexing massive channels\n\nIf you add a massive channel (one with several thousand videos) to TubeSync and choose \"index\nevery hour\" or a similarly short interval; it's entirely possible that your TubeSync install may\nspend its entire time indexing the channel, over and over again, without\ndownloading any media. Check your tasks for the status of your TubeSync install.\n\n**Be nice.** It's entirely possible that your IP address could get throttled and/or banned, by the\nsource, if you try to crawl extremely large amounts quickly. **Try to be polite\nwith the smallest amount of indexing and concurrent downloads possible for your needs.**\n\nOnly, if you absolutely must, should you increase [`TUBESYNC_WORKERS`](#advanced-configuration) above its default value.\nThe maximum the software accepts is `8` threads per queue worker process.\nBy default, up to `3` tasks will be executing concurrently.\nThe maximum is `24` concurrent tasks.\n\n# FAQ\n\n### Can I use TubeSync to download single videos?\n\nNo, TubeSync is designed to repeatedly scan and download new media from channels or\nplaylists. If you want to download single videos the best suggestion would be to create\nyour own playlist, add the playlist to TubeSync and then add single videos to your\nplaylist as you browse about YouTube. Your \"favourites\" playlist of videos will download\nautomatically.\n\n### Does TubeSync support any other video platforms?\n\nAt the moment, no. This is a pre-release. The library TubeSync uses that does most\nof the downloading work, `yt-dlp`, supports many hundreds of video sources so it's\nlikely more will be added to TubeSync if there is demand for it.\n\n### Is there a progress bar?\n\nNo, in fact, there is no JavaScript at all in the web interface at the moment. TubeSync\nis designed to be more set-and-forget than something you watch download. You can see\nwhat active tasks are being run in the \"tasks\" tab and if you want to see exactly what\nyour install is doing check the container logs.\n\n### Are there alerts when a download is complete?\n\nNo, this feature is best served by existing services such as the excellent \n[Tautulli](https://tautulli.com/) which can monitor your Plex server and send alerts\nthat way.\n\n### There are errors in my \"tasks\" tab!\n\nYou only really need to worry about these if there is a permanent failure. Some errors\nare temporary and will be retried for you automatically, such as a download got\ninterrupted and will be tried again later. Sources with permanent errors (such as no\nmedia available because you got a channel name wrong) will be shown as errors on the\n\"sources\" tab.\n\n### What is TubeSync written in?\n\nPython3 using Django, embedding yt-dlp. It's pretty much glue between other much\nlarger libraries.\n\nNotable libraries and software used:\n\n * [Django](https://www.djangoproject.com/)\n * [yt-dlp](https://github.com/yt-dlp/yt-dlp)\n * [ffmpeg](https://ffmpeg.org/)\n * [Django Background Tasks](https://github.com/arteria/django-background-tasks/)\n * [django-sass](https://github.com/coderedcorp/django-sass/)\n * The container bundles with `s6-init` and `nginx`\n\nSee the [Pipfile](https://github.com/meeb/tubesync/blob/main/Pipfile) for a full list.\n\n### Can I get access to the full Django admin?\n\nYes, although pretty much all operations are available through the front-end interface\nand you can probably break things by playing in the admin. If you still want to access\nit you can run:\n\n```bash\n$ docker exec -ti tubesync python3 /app/manage.py createsuperuser\n```\n\nAnd follow the instructions to create an initial Django superuser, once created, you\ncan log in at http://localhost:4848/admin\n\n### Are there user accounts or multi-user support?\n\nThere is support for basic HTTP authentication by setting the `HTTP_USER` and\n`HTTP_PASS` environment variables. There is not support for multi-user or user\nmanagement.\n\n### Does TubeSync support HTTPS?\n\nNo, you should deploy it behind an HTTPS-capable proxy if you want this (nginx, caddy,\netc.). Configuration of this is beyond the scope of this README.\n\n### What architectures does the container support?\n\nOnly two are supported, for the moment:\n- `amd64` (most desktop PCs and servers)\n-  `arm64`\n(modern ARM computers, such as the Raspberry Pi 3 or later)\n\nOthers may be made available, if there is demand.\n\n### The pipenv install fails with \"Locking failed\"!\n\nMake sure that you have `mysql_config` or `mariadb_config` available, as required by the python module `mysqlclient`. On Debian-based systems this is usually found in the package `libmysqlclient-dev`\n\n\n# Advanced configuration\n\nThere are a number of other environment variables you can set. These are, mostly,\n**NOT** required to be set in the default container installation, they are really only\nuseful if you are manually installing TubeSync in some other environment. These are:\n\n| Name                         | What                                                          | Example                                                                       |\n| ---------------------------- | ------------------------------------------------------------- |-------------------------------------------------------------------------------|\n| DJANGO_SECRET_KEY            | Django's SECRET_KEY                                           | YJySXnQLB7UVZw2dXKDWxI5lEZaImK6l                   |\n| DJANGO_URL_PREFIX            | Run TubeSync in a sub-URL on the web server                   | /somepath/                                                                    |\n| TUBESYNC_DEBUG               | Enable debugging                                              | True                                                                          |\n| TUBESYNC_HOSTS               | Django's ALLOWED_HOSTS, defaults to `*`                       | tubesync.example.com,otherhost.com                 |\n| TUBESYNC_RESET_DOWNLOAD_DIR  | Toggle resetting `/downloads` permissions, defaults to True   | True                                                                          |\n| TUBESYNC_VIDEO_HEIGHT_CUTOFF | Smallest video height in pixels permitted to download         | 240                                                                           |\n| TUBESYNC_RENAME_SOURCES      | Rename media files from selected sources                      | Source1_directory,Source2_directory                |\n| TUBESYNC_RENAME_ALL_SOURCES  | Rename media files from all sources                           | True                                                                          |\n| TUBESYNC_DIRECTORY_PREFIX    | Enable `video` and `audio` directory prefixes in `/downloads` | True                                                                          |\n| TUBESYNC_SHRINK_NEW          | Filter unneeded information from newly retrieved metadata     | True                                                                          |\n| TUBESYNC_SHRINK_OLD          | Filter unneeded information from metadata loaded from the database | True                                                                     |\n| TUBESYNC_WORKERS             | Number of background threads per (task runner) process. Default is 1. Max allowed is 8. | 2                                                  |\n| GUNICORN_WORKERS             | Number of `gunicorn` (web request) workers to spawn           | 3                                                                             |\n| LISTEN_HOST                  | IP address for `gunicorn` to listen on                        | 127.0.0.1                                                                     |\n| LISTEN_PORT                  | Port number for `gunicorn` to listen on                       | 8080                                                                          |\n| HTTP_USER                    | Sets the username for HTTP basic authentication               | some-username                                                                 |\n| HTTP_PASS                    | Sets the password for HTTP basic authentication               | some-secure-password                                                          |\n| DATABASE_CONNECTION          | Optional external database connection details                 | postgresql://user:pass@host:port/database          |\n\n\n# Manual, non-containerised, installation\n\nAs a relatively normal Django app you can run TubeSync without the container. Beyond\nfollowing this rough guide, you are on your own and should be knowledgeable about\ninstalling and running WSGI-based Python web applications before attempting this.\n\n1. Clone or download this repo\n2. Make sure you're running a modern version of Python (\u003e=3.9) and have Pipenv\n   installed\n3. Set up the environment with `pipenv install`\n4. Copy `tubesync/tubesync/local_settings.py.example` to\n   `tubesync/tubesync/local_settings.py` and edit it as appropriate\n5. Run migrations with `./manage.py migrate`\n6. Collect static files with `./manage.py collectstatic`\n6. Set up your prefered WSGI server, such as `gunicorn` pointing it to the application\n   in `tubesync/tubesync/wsgi.py`\n7. Set up your proxy server such as `nginx` and forward it to the WSGI server\n8. Check the web interface is working\n9. Run `./manage.py process_tasks` as the background task worker to index and download\n   media. This is a non-detaching process that will write logs to the console. For long\n   term running you could use a terminal multiplexer such as `tmux`, or create\n   `systemd` unit to run it.\n\n\n# Tests\n\nThere is a moderately comprehensive test suite focusing on the custom media format\nmatching logic and that the front-end interface works. You can run it via Django:\n\n```bash\n$ ./manage.py test --verbosity=2\n```\n\n\n# Contributing\n\nAll properly formatted and sensible pull requests, issues and comments are welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeeb%2Ftubesync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmeeb%2Ftubesync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmeeb%2Ftubesync/lists"}