{"id":26475431,"url":"https://github.com/opencast/zoom-ingest","last_synced_at":"2026-05-18T08:31:10.405Z","repository":{"id":40565195,"uuid":"306662120","full_name":"opencast/zoom-ingest","owner":"opencast","description":"Zoom to Opencast Ingester","archived":false,"fork":false,"pushed_at":"2023-11-01T09:12:19.000Z","size":613,"stargazers_count":2,"open_issues_count":19,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-14T14:53:46.424Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opencast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"license.lgpl","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-10-23T14:33:02.000Z","updated_at":"2023-03-02T09:01:58.000Z","dependencies_parsed_at":"2022-08-09T23:21:06.438Z","dependency_job_id":"3ef532e3-3914-4f0a-9f50-eb77fb7f2727","html_url":"https://github.com/opencast/zoom-ingest","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencast%2Fzoom-ingest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencast%2Fzoom-ingest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencast%2Fzoom-ingest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opencast%2Fzoom-ingest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opencast","download_url":"https://codeload.github.com/opencast/zoom-ingest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244520140,"owners_count":20465632,"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":[],"created_at":"2025-03-19T23:17:06.223Z","updated_at":"2026-05-18T08:31:05.381Z","avatar_url":"https://github.com/opencast.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Opencast-Zoom-Ingester\n============================\n\nThis utility provides a (very basic) web ui for manually triggering the download,\nand ingestion of Zoom cloud recordings into your Opencast infrastructure.  This is\ndesigned to be scalable in terms of number of parallel downloads, while also being\nrun entirely on local infrastructure.\n\n**Requirements**\n\nPython packages:\n\n- `pika`\n- `requests`\n- `zoomus`\n- `flask`\n- `gunicon`\n- `sqlalchemy`\n- `xmltodict`\n- `mysqlclient` (Optional)\n\nExternal dependencies:\n\n- A RabbitMQ server\n- A database server (tested against sqlite and mariadb 10)\n\n**Basic configuration:**\n\nThe settings.ini file contains the configuration for this utility.  There are five sections at present:\n\n1. Logging:\n\nThe `debug` key controls verbose logging.  For production use you probably want this to be false.\n\n2. Zoom:\n\nThis is where you configure your [Server-To-Server OAUTH](https://developers.zoom.us/docs/internal-apps/s2s-oauth/)\napplication.  You *must* create such an application in your account - this tool is not something you can subscribe to\ndirectly.\n\nTo create the app:\n- Create a Server-to-Server OAuth App within the Zoom App Marketplace.  Beware, there is an standard (non\n  server-to-server) OAuth application type which will not work for this application.\n  - Your `Account ID`, `Client ID`, and `Client Secret` should be copied into the `Zoom` section in settings.ini.\n- Grant the following scopes to your application:\n  - `/contact:read:admin`, which is required for user search to work\n  - `/user:read:admin`, which is required for user search to work, and user data to populate\n  - `/recording:read:admin`, which is required to read the recording data\n\n3. Webhook:\n\nThis utilty supports event-driven ingestion.  When a meeting finishes it would be automatically ingested.\nThis is *disabled* unless both a default workflow id, and one of series or acl id are set.  The webhook must also be\nconfigured on Zoom's end, which is done in the Zoom app under the `Feature` section of the Zoom app you created above.\nTo accomplish this you must:\n- Enable `Event Subscriptions` for the following events:\n  - `All Recordings have completed`\n  - `Recording Renamed` events.\nFor security purposes the `Secret Token` from the `Features` section in Zoom should be copied to the `secret` config\nkey.  Without this secret the incoming webhook POSTs are not verified to be originating from Zoom's servers.\n\n4. Opencast:\n\nThis is the url, as well as user and password to use when ingesting to Opencast.  Note that this has only\nbeen tested with the digest user, although there is no reason it would not work with another user.  Note that\nthe code assumes the use of the digest user, so if non-digest users are required some minor modifications will be\nrequired.\n\n5. Rabbit:\n\nThis is the rabbit credentials and url.  I have been testing with rabbit running in docker (via `rabbit.sh`),\nand everything worked out of the box without further configuration.  Rabbit running outside of Docker might\nrequire additional fiddling.\n\n**Installation**\n\nThe packages above can all be installed via *pip*: `pip3 install -r requirements.txt`.  Note that depending\non the target database you may need to install system packages, and/or additional pip packages.  Notably, on my\nDebian system the mysql python bindings required the mysql client *development* package to provide the relevant\nheaders.  For public release I plan to test against a wider variety of system so these instructions can be more\ncomplete.\n\n**Database Setup**\n\nA user with appropriate permissions for an existing (preferably blank) schema should exist.  SQLAlchemy will\ncreate the tables it requires at runtime.\n\n**Usage**\n\nThis utiltiy contains two major components: The webhook, and the uploader.\n\nWebhook: This module provides the webhook, as well as the UI that your users interact with.\nWhen a webhook fires, or a user triggers an ingest, a message is generated and sent to RabbitMQ.\nThis queue spools the requests for later ingestion by the uploader(s).  To run the webhook use\n`webhook.sh`.  This starts a server on port 8000 listening on all interfaces.  Note that this\nserver provides *no* authentication at all, so please apply appropriate firewall ACLs.\n\nUploader: This module listens for events in the Rabbit queue, and then ingests those recordings\nto Opencast.  This module can be run in parallel across multiple machines, provided that there\nis a shared database for all the nodes to connect to so that state can be maintained.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopencast%2Fzoom-ingest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopencast%2Fzoom-ingest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopencast%2Fzoom-ingest/lists"}