{"id":19156920,"url":"https://github.com/bertrandmartel/ustream-dl","last_synced_at":"2025-07-31T06:09:47.017Z","repository":{"id":94808963,"uuid":"109647290","full_name":"bertrandmartel/ustream-dl","owner":"bertrandmartel","description":"Experimental python script for downloading a stream (which has ended) from ustream.tv","archived":false,"fork":false,"pushed_at":"2018-01-08T19:36:56.000Z","size":10,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T07:48:35.445Z","etag":null,"topics":["flv","python","ustream"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bertrandmartel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2017-11-06T04:22:57.000Z","updated_at":"2024-07-29T00:15:21.000Z","dependencies_parsed_at":"2023-03-24T13:50:48.512Z","dependency_job_id":null,"html_url":"https://github.com/bertrandmartel/ustream-dl","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bertrandmartel/ustream-dl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Fustream-dl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Fustream-dl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Fustream-dl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Fustream-dl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bertrandmartel","download_url":"https://codeload.github.com/bertrandmartel/ustream-dl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertrandmartel%2Fustream-dl/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267997175,"owners_count":24178251,"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","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["flv","python","ustream"],"created_at":"2024-11-09T08:36:25.474Z","updated_at":"2025-07-31T06:09:46.990Z","avatar_url":"https://github.com/bertrandmartel.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Download stream from ustream.tv\n\n[![CircleCI](https://img.shields.io/circleci/project/bertrandmartel/ustream-dl.svg?maxAge=2592000?style=plastic)](https://circleci.com/gh/bertrandmartel/ustream-dl) \n[![License](http://img.shields.io/:license-mit-blue.svg)](LICENSE.md)\n\nExperimental python script for downloading a stream (which has ended) from ustream.tv\n\nThe goal is to automate the process to get the video file for the whole stream in FLV format\n\nThis stream is protected by a dumb authentication (enter your name, role, email, phone num)\n\n## Usage\n\n```python\npip3 install -r requirements.txt\npython3 ustream.py\n```\n\n## Call Flow\n\n![processing](https://user-images.githubusercontent.com/5183022/32425330-9a66b3ba-c2b2-11e7-8c9c-4e693dd7b8c2.png)\n\n[link to this diagram](https://bertrandmartel.github.io/callflow-workshop/?CYSwhg5gTmC2D6IB2AHArgFwLwoJ4YAsB7JAUgCYAGAZwGMoQUMBaUgZgFE1qMoBTOADoMANwAUBDBhTUAlOwCCFShD4ZltAmCRI+AG2UhgygGZQisZSnMijfY1TRQDlBd14DYw8ZOlzWnHiEJMp0DEyKypKwBlT81Cgk1HykrkhEGClURCJ8UFb4xGRUYYzqbEol9GAoGlo6+ogOlGYWyrBqYMoYkKkKQUWh9GUBXDz8QqISUjLyFcpgmAR8SBggtGCZygDuIITKwGiwsLiGqJjKYkhwWQDCynywYCB68q7uE15TvrOjAyFVcLlSo0FbNABSAGUAPIAOSiYGoBGU8USSGSfX+xRowyYow+nm80z8cxBGz0sRUajq2l0lNoJEyq2UCgACgBJPoEyY+Gb+dgcLFDIGREpgmkNSnATZdKjIWh6NCgJAQZR6EA8ZREEzKWzAPhEQzGVxCwEjAXcr7ibZ8ABG1CItAA1mpSVqUCsdnaHc7qVQGQ1aGsQibCgCcUD8eNCVMbfbHS6MG6xUhmgHdEGNBYnqmudGeWI4z7E7I-mHsaUIvM4nxaHwQLllFC4aEPHAziYiFAnsHsfLFcrVVR1ZrsjqqFokXxqH10ltsrl8lRTRGyqLKCgwDAKfoDkRtkg9EQwM0wBTlAAxAAyADU6mgkE7ZxkspQcnkCsEK7jgSjHu-L1vKIBH1KAZyoVpLH9AgHyfABWAAhABGZgyDggARZ95zfRdP0GM0qzJEgNnUKhrzvaDYNIRCULQzCqAwQ1KMfSgsNfd8lw3cthTXatKAZPB7xY7omLfTB0AwQQTD0EQADJQEgGAEEIR4+CwagQFgFA9D4WSwDreAVI6LAID2GDbVkgMTBACB4FsPhtiwRc1nJWTdlTfd4A0gAvPh4CIJgQCSLBSAAdgQihyGc9Yz0iyJwsi3ZgH2chyEUJCqFY0L6PuVLiAYbzGVi1L4oivL6wgSQ4oqcg4KyzDstktYMB0rB0P3Q9j2afMoJaF52OxS1vCAA)\n\n## Process \n\n* get channel id from the page : https://www.ustream.tv/channel/curJSsZFUUu\n* authenticate with dummy input (name, role, email, phone numb.) to get the `hash` field via the url : \n\n    `https://www.ustream.tv/ajax/viewer-registration/save/{channel_id}/channel/{channel_id}.json`\n\n* call the get channel content API (with the auth `hash`) to get the list of video : \n\n    `https://www.ustream.tv/ajax/viewing-experience/channel/{channel_id}/content.json`\n\n* open websocket connection to :\n\n    `wss://r{8_digit_random}-1-{video_id}-recorded-wss-live.ums.ustream.tv/1/ustream` \n\nand send a `connect` action with the following parameter : \n\n```\n{\n    \"cmd\":\"connect\",\n    \"args\":[\n        {\n            \"type\":\"viewer\",\n            \"appId\":3,\n            \"appVersion\":2,\n            \"isOffairRecorded\":True,\n            \"referrer\": url,\n            \"media\": video_id,\n            \"application\":\"recorded\",\n            \"hash\":json.dumps(auth[\"hash\"])\n        }\n    ]\n}\n```\nThen 3 responses frames are received including one with `stream` information which gives chunk url format and list of hashes to download. This includes `mp4/segmented` \u0026 `flv/segmented`. Here we download only flv/segmented\n* download all chunk (for [this video](https://www.ustream.tv/channel/curJSsZFUUu) it's 14XX .flv file of 6 sec.)\n* remove FLV headers of all chunk \u003e 0 (eg chunk1 to chunkn excluding the first chunk)\n* concatenate all those chunk to the first chunk : 0.flv\n* copy the flv file to the specified location\n\nNote that this is for personal use or education purpose only. For other usage, use [the official API](http://developers.ustream.tv/channel-api/)\n\n## Convert the flv output to mp4 \n\nUse ffmpeg : \n\n```\nffmpeg -i stream.flv -codec copy stream.mp4\n```\n\n## References\n\n* [Video File Format Specification Version 10 - Adobe](https://www.google.fr/url?sa=t\u0026rct=j\u0026q=\u0026esrc=s\u0026source=web\u0026cd=1\u0026ved=0ahUKEwjfts6Xk6nXAhVILewKHbbFCOUQFggoMAA\u0026url=https%3A%2F%2Fwww.adobe.com%2Fcontent%2Fdam%2Facom%2Fen%2Fdevnet%2Fflv%2Fvideo_file_format_spec_v10.pdf\u0026usg=AOvVaw0wwfZyn48I7P4PNPwn736E)\n* [flvmeta tool](https://github.com/noirotm/flvmeta)\n\n## License \n\nThe MIT License (MIT) Copyright (c) 2017 Bertrand Martel","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertrandmartel%2Fustream-dl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbertrandmartel%2Fustream-dl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertrandmartel%2Fustream-dl/lists"}