{"id":38256340,"url":"https://github.com/dir01/mediary","last_synced_at":"2026-03-01T20:03:52.323Z","repository":{"id":141985555,"uuid":"519489350","full_name":"dir01/mediary","owner":"dir01","description":"Media service: downloads (torrent/youtube/yt-dl), transforms it (ffmpeg), uploads (s3 presigned url)","archived":false,"fork":false,"pushed_at":"2025-03-28T11:05:09.000Z","size":456,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T11:31:12.940Z","etag":null,"topics":["media-transform","torrent-downloader"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dir01.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2022-07-30T10:45:34.000Z","updated_at":"2025-03-28T10:59:33.000Z","dependencies_parsed_at":"2023-12-01T20:33:51.204Z","dependency_job_id":"6477981a-155f-4a78-a7f5-5ebbd03c8afd","html_url":"https://github.com/dir01/mediary","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/dir01/mediary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dir01%2Fmediary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dir01%2Fmediary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dir01%2Fmediary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dir01%2Fmediary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dir01","download_url":"https://codeload.github.com/dir01/mediary/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dir01%2Fmediary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28491586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T00:50:05.742Z","status":"ssl_error","status_checked_at":"2026-01-17T00:43:11.982Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["media-transform","torrent-downloader"],"created_at":"2026-01-17T01:31:54.034Z","updated_at":"2026-03-01T20:03:52.316Z","avatar_url":"https://github.com/dir01.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mediary\n\n\n## What is Mediary\nMediary is a service that can download, convert and upload media\n\nExample use cases:\n\n- Given a magnet link, download files A, B and C, glue them together and upload to this pre-signed S3 URL\n- Given a YouTube video link, download audio, convert it to .mp3, and upload to this pre-signed S3 URL\n- (to be done) Given a link to a single file, just take it and upload it to this pre-signed S3 URL\n\n\n## API\n- `GET /metadata` - returns metadata for a given media link. You are going to need it if you want \nto pick and choose which files should be processed.\n- `POST /job` - creates a task to upload media. Describes the source URL, files at source URL\n    to be processed, what transformation to apply and where to upload the result.\n- `GET /job/{id}` - returns the status of a job.\n\n\n## Examples\n\u003c!-- start autogenerated samples --\u003e\n### `/metadata` - Timeouts\n\nBy default, the endpoint will time out pretty quickly,\nprobably sooner than it takes to fetch metadata of a torrent, for example.\n\nIn such cases, the endpoint will return a `202 Accepted` status code and a message `{\"status\": \"accepted\"}`\n\nFeel free to repeat your request later: metadata is still being fetched in background.\n\n\n```\n$ curl -X GET '/metadata?url=magnet:?xt=urn:btih:0000000000000000000000000000000000000001'\n{\"status\": \"accepted\"}\n```\n\n\n### `/metadata/long-polling`\n\nIn case you'd rather wait for the metadata to be fetched, you can use the long-polling endpoint.\n\nIt will not return a response until the metadata is fetched.\n\nThere is still a timeout on the request, but it's pretty long (5 minutes).\n\n```\n$ curl -X GET '/metadata/long-polling?url=magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8'\n{\n  \"url\": \"magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8\",\n  \"name\": \"mediary-test-collection\",\n  \"variants\": [\n    {\n      \"id\": \"chapter1.mp3\",\n      \"length_bytes\": 30\n    },\n    {\n      \"id\": \"chapter2.mp3\",\n      \"length_bytes\": 30\n    }\n  ],\n  \"allow_multiple_variants\": true,\n  \"downloader_name\": \"torrent\"\n}\n```\n\n\n### `/metadata` - Cached\n\nIt goes without saying, that once the metadata is fetched, it is cached.\n\nSo all consecutive requests for the same URL will return the same metadata, and immediately.\n\n```\n$ curl -X GET '/metadata?url=magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8'\n{\n  \"url\": \"magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8\",\n  \"name\": \"mediary-test-collection\",\n  \"variants\": [\n    {\n      \"id\": \"chapter1.mp3\",\n      \"length_bytes\": 30\n    },\n    {\n      \"id\": \"chapter2.mp3\",\n      \"length_bytes\": 30\n    }\n  ],\n  \"allow_multiple_variants\": true,\n  \"downloader_name\": \"torrent\"\n}\n```\n\n\n### `POST /metadata`\n\nAs you could've noticed, in previous calls part of the URL was lost.\nTo work around it, service also supports `POST` requests to `/metadata` endpoint.\nIn this case, you can pass the URL in the JSON body of the request.\n\n```\n$ curl -X POST '/metadata'--data-raw='{\"url\": \"magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8\"}'\n{\n  \"url\": \"magnet:?xt=urn:btih:62f0dab4e2137fc19e89eb363e72799ca85ccbe8\",\n  \"name\": \"mediary-test-collection\",\n  \"variants\": [\n    {\n      \"id\": \"chapter1.mp3\",\n      \"length_bytes\": 30\n    },\n    {\n      \"id\": \"chapter2.mp3\",\n      \"length_bytes\": 30\n    }\n  ],\n  \"allow_multiple_variants\": true,\n  \"downloader_name\": \"torrent\"\n}\n```\n\n\n### `/metadata` - YouTube\n\nThe endpoint also supports fetching metadata for YouTube videos.\nNote that instead of file paths we get different options of desired formats:\nVideo, Audio, different qualities, etc.\n\nThis will allow you to choose the format you want to download later in the same UI as for torrent files.\n\nSince it does not make sense to concatenate different versions of the same video,\nresponse also will have `'\"allow_multiple_files\": false`.\nTake this into account while presenting format options to user\n\n```\n$ curl -X GET '/metadata?url=https://www.youtube.com/watch?v=kPN-uWB28X8'\n{\"status\": \"accepted\"}\n```\n\n\nand then later\n\n```\n$ curl -X GET '/metadata?url=https://www.youtube.com/watch?v=kPN-uWB28X8'\n{\n  \"url\": \"https://www.youtube.com/watch?v=kPN-uWB28X8\",\n  \"name\": \"Miles Davis - Baby won't you please come home\",\n  \"variants\": [\n    {\n      \"id\": \"Video (mp4)\"\n    },\n    {\n      \"id\": \"Audio (mp3), High Quality\"\n    },\n    {\n      \"id\": \"Audio (mp3), Medium Quality\"\n    },\n    {\n      \"id\": \"Audio (mp3), Low Quality\"\n    }\n  ],\n  \"allow_multiple_variants\": false,\n  \"downloader_name\": \"ytdl\"\n}\n```\n\n\n### `/jobs`\n\nPOST to `/jobs` will schedule for background execution a process of downloading, converting/processing and uploading the media.\nOnly required parameters are `url` and `type`. `type` signifies the type of operation to be performed.\nEach operation can require some additional parameters, passed as `params`. For example, `concatenate` job\nrequires a list of files to be concatenated and, optionally, an `audioCodec` to be used for the output file.\n\n```\n$ curl -X POST '/jobs'--data-raw='{\n\t\"url\": \"magnet:?xt=urn:btih:fed6a13c3cc5fb6a440a11c59ed3672a103bca3e\",\n\t\"type\": \"concatenate\",\n\t\"params\": {\n\t\t\"variants\": [\n\t\t\t\"01-001.mp3\",\n\t\t\t\"01-002.mp3\"\n\t\t],\n\t\t\"audioCodec\": \"mp3\",\n\t\t\"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20260301T173626Z\u0026X-Amz-Expires=900\u0026X-Amz-Security-Token=dummy\u0026X-Amz-SignedHeaders=host\u0026x-id=PutObject\u0026X-Amz-Signature=aa6866f1de0035e32f399065d1a6ca26668a8d1547ffa388ef0249491279a562\"\n\t}\n}'\n{\"status\": \"accepted\", \"id\": \"d382000a999d49c2c2e37286fa4d5bb3\"}\n```\n\n\n### `/jobs/:id`\n\nSince jobs can run for a long time, job creation api responds immediately with a job ID.\nTo check the status of the job, you can use the `/jobs/:id` endpoint.\n\n0s after starting the job:\n\n```\n$ curl -X GET '/jobs/d382000a999d49c2c2e37286fa4d5bb3'\n{\n  \"url\": \"magnet:?xt=urn:btih:fed6a13c3cc5fb6a440a11c59ed3672a103bca3e\",\n  \"type\": \"concatenate\",\n  \"params\": {\n    \"audioCodec\": \"mp3\",\n    \"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\\u0026X-Amz-Date=20260301T173626Z\\u0026X-Amz-Expires=900\\u0026X-Amz-Security-Token=dummy\\u0026X-Amz-SignedHeaders=host\\u0026x-id=PutObject\\u0026X-Amz-Signature=aa6866f1de0035e32f399065d1a6ca26668a8d1547ffa388ef0249491279a562\",\n    \"variants\": [\n      \"01-001.mp3\",\n      \"01-002.mp3\"\n    ]\n  },\n  \"id\": \"d382000a999d49c2c2e37286fa4d5bb3\",\n  \"status\": \"downloading\"\n}\n```\n\n\n1s later:\n\n```\n$ curl -X GET '/jobs/d382000a999d49c2c2e37286fa4d5bb3'\n{\n  \"url\": \"magnet:?xt=urn:btih:fed6a13c3cc5fb6a440a11c59ed3672a103bca3e\",\n  \"type\": \"concatenate\",\n  \"params\": {\n    \"audioCodec\": \"mp3\",\n    \"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\\u0026X-Amz-Date=20260301T173626Z\\u0026X-Amz-Expires=900\\u0026X-Amz-Security-Token=dummy\\u0026X-Amz-SignedHeaders=host\\u0026x-id=PutObject\\u0026X-Amz-Signature=aa6866f1de0035e32f399065d1a6ca26668a8d1547ffa388ef0249491279a562\",\n    \"variants\": [\n      \"01-001.mp3\",\n      \"01-002.mp3\"\n    ]\n  },\n  \"id\": \"d382000a999d49c2c2e37286fa4d5bb3\",\n  \"status\": \"processing\"\n}\n```\n\n\n0s later:\n\n```\n$ curl -X GET '/jobs/d382000a999d49c2c2e37286fa4d5bb3'\n{\n  \"url\": \"magnet:?xt=urn:btih:fed6a13c3cc5fb6a440a11c59ed3672a103bca3e\",\n  \"type\": \"concatenate\",\n  \"params\": {\n    \"audioCodec\": \"mp3\",\n    \"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\\u0026X-Amz-Date=20260301T173626Z\\u0026X-Amz-Expires=900\\u0026X-Amz-Security-Token=dummy\\u0026X-Amz-SignedHeaders=host\\u0026x-id=PutObject\\u0026X-Amz-Signature=aa6866f1de0035e32f399065d1a6ca26668a8d1547ffa388ef0249491279a562\",\n    \"variants\": [\n      \"01-001.mp3\",\n      \"01-002.mp3\"\n    ]\n  },\n  \"id\": \"d382000a999d49c2c2e37286fa4d5bb3\",\n  \"status\": \"uploading\",\n  \"result_media_duration\": 236168000,\n  \"result_file_bytes\": 2614\n}\n```\n\n\n0s later:\n\n```\n$ curl -X GET '/jobs/d382000a999d49c2c2e37286fa4d5bb3'\n{\n  \"url\": \"magnet:?xt=urn:btih:fed6a13c3cc5fb6a440a11c59ed3672a103bca3e\",\n  \"type\": \"concatenate\",\n  \"params\": {\n    \"audioCodec\": \"mp3\",\n    \"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\\u0026X-Amz-Date=20260301T173626Z\\u0026X-Amz-Expires=900\\u0026X-Amz-Security-Token=dummy\\u0026X-Amz-SignedHeaders=host\\u0026x-id=PutObject\\u0026X-Amz-Signature=aa6866f1de0035e32f399065d1a6ca26668a8d1547ffa388ef0249491279a562\",\n    \"variants\": [\n      \"01-001.mp3\",\n      \"01-002.mp3\"\n    ]\n  },\n  \"id\": \"d382000a999d49c2c2e37286fa4d5bb3\",\n  \"status\": \"complete\",\n  \"result_media_duration\": 236168000,\n  \"result_file_bytes\": 2614\n}\n```\n\n\n### Downloading YouTube audio\n\nTo download a YouTube video, you need to pass the URL of the video to the `/jobs` endpoint.\n\n```\n$ curl -X POST '/jobs'--data-raw='{\n\t\"url\": \"https://www.youtube.com/watch?v=kPN-uWB28X8\",\n\t\"type\": \"upload_original\",\n\t\"params\": {\n\t\t\"variant\": \"Audio (mp3), Low Quality\",\n\t\t\"uploadUrl\": \"http://localhost:55063/some-bucket/some-path/some-file.some-ext?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=dummy%2F20260301%2Fus-east-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20260301T173627Z\u0026X-Amz-Expires=900\u0026X-Amz-Security-Token=dummy\u0026X-Amz-SignedHeaders=host\u0026x-id=PutObject\u0026X-Amz-Signature=4b3727272ed4813cf47c7711271a8cb3bad37ce7bb82dfed2bd6831f77cc9445\"\n\t}\n}'\n{\"status\": \"accepted\", \"id\": \"c6bfba4b17a25c613cdb472c35839164\"}\n```\n\n\u003c!-- stop autogenerated samples --\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdir01%2Fmediary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdir01%2Fmediary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdir01%2Fmediary/lists"}