{"id":31541301,"url":"https://github.com/membraneframework/ex_hls","last_synced_at":"2026-01-20T17:02:56.268Z","repository":{"id":301161155,"uuid":"962051617","full_name":"membraneframework/ex_hls","owner":"membraneframework","description":"An Elixir package for handling HLS streams","archived":false,"fork":false,"pushed_at":"2025-11-13T14:42:41.000Z","size":3437,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-11-13T16:27:39.319Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/membraneframework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-07T15:15:57.000Z","updated_at":"2025-10-23T12:38:13.000Z","dependencies_parsed_at":"2025-07-14T12:03:53.179Z","dependency_job_id":"3220b301-ae09-45ad-bbf1-8e3948f4346f","html_url":"https://github.com/membraneframework/ex_hls","commit_stats":null,"previous_names":["membraneframework-labs/ex_hls","membraneframework/ex_hls"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/membraneframework/ex_hls","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fex_hls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fex_hls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fex_hls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fex_hls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/membraneframework","download_url":"https://codeload.github.com/membraneframework/ex_hls/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/membraneframework%2Fex_hls/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28607624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T16:10:39.856Z","status":"ssl_error","status_checked_at":"2026-01-20T16:10:39.493Z","response_time":117,"last_error":"SSL_read: 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":[],"created_at":"2025-10-04T10:58:51.536Z","updated_at":"2026-01-20T17:02:56.262Z","avatar_url":"https://github.com/membraneframework.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExHLS\n\n[![Hex.pm](https://img.shields.io/hexpm/v/ex_hls.svg)](https://hex.pm/packages/ex_hls)\n[![API Docs](https://img.shields.io/badge/api-docs-yellow.svg?style=flat)](https://hexdocs.pm/ex_hls)\n[![CircleCI](https://circleci.com/gh/membraneframework/ex_hls.svg?style=svg)](https://circleci.com/gh/membraneframework/ex_hls)\n\nThis repository contains ExHLS - an Elixir package for handling HLS streams.\n\nIt's a part of the [Membrane Framework](https://membrane.stream).\n\n## Installation\n\nThe package can be installed by adding `ex_hls` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:ex_hls, \"~\u003e 0.2.0\"}\n  ]\nend\n```\n\n## Usage\n\nTo read HLS stream from the `.m3u8 playlist`, start the client with:\n```elixir\nclient = ExHLS.Client.new(\u003cURI of the .m3u8 playlist\u003e)\n```\n\nThen you can inspect the variants available in your playlist:\n```elixir\nExHLS.Client.get_variants(client)\n# Returns:\n#   %{\n#     0 =\u003e %{\n#       id: 0,\n#       name: \"720\",\n#       uri: \"url_0/193039199_mp4_h264_aac_hd_7.m3u8\",\n#       codecs: \"mp4a.40.2,avc1.64001f\",\n#       bandwidth: 2149280,\n#       resolution: {1280, 720},\n#       frame_rate: nil\n#     },\n#     ...\n#   }\n```\n\nIf there are multiple variants available, you need to choose one of them with:\n```elixir\nExHLS.Client.choose_variant(client, \u003cid\u003e)\n```\nwhere `\u003cid\u003e` is the `id` field of the entry returned by `ExHLS.Client.get_variants/1`.\n\nNow you can get the Elixir stream containing media chunks:\n```elixir\nstream = ExHLS.Client.generate_stream(client)\nEnum.take(stream, 5)\n# Returns:\n# [\n#   %ExHLS.Chunk{\n#     payload: \u003c\u003c220, 0, 76, 97, 118, 99, 54, 49, 46, 51, 46, 49, 48, 48, 0, 66,\n#       32, 8, 193, 24, 56\u003e\u003e,\n#     pts_ms: 0,\n#     dts_ms: 0,\n#     track_id: 2,\n#     metadata: %{},\n#     media_type: :audio\n#   },\n#   %ExHLS.Chunk{\n#     payload: \u003c\u003c0, 0, 2, 171, 6, 5, 255, 255, 167, 220, 69, 233, 189, 230, 217,\n#       72, 183, 150, 44, 216, 32, 217, 35, 238, 239, 120, 50, 54, 52, 32, 45, 32,\n#       99, 111, 114, 101, 32, 49, 54, 52, 32, 114, 51, 49, 48, 56, 32, ...\u003e\u003e,\n#     pts_ms: 0,\n#     dts_ms: 0,\n#     track_id: 1,\n#     metadata: %{},\n#     media_type: :video\n#   },\n#   %ExHLS.Chunk{\n#     payload: \u003c\u003c33, 16, 4, 96, 140, 28\u003e\u003e,\n#     pts_ms: 23,\n#     dts_ms: 23,\n#     track_id: 2,\n#     metadata: %{},\n#     media_type: :audio\n#   },\n#   %ExHLS.Chunk{\n#     payload: \u003c\u003c0, 0, 1, 222, 65, 154, 34, 108, 67, 63, 254, 169, 150, 0, 4, 1,\n#       131, 32, 3, 199, 34, 90, 245, 77, 218, 222, 66, 91, 35, 3, 208, 204, 165,\n#       117, 149, 218, 168, 161, 173, 73, 104, 105, 159, 56, 151, ...\u003e\u003e,\n#     pts_ms: 40,\n#     dts_ms: 40,\n#     track_id: 1,\n#     metadata: %{},\n#     media_type: :video\n#   },\n#   %ExHLS.Chunk{\n#     payload: \u003c\u003c33, 16, 4, 96, 140, 28\u003e\u003e,\n#     pts_ms: 46,\n#     dts_ms: 46,\n#     track_id: 2,\n#     metadata: %{},\n#     media_type: :audio\n#   }\n# ]\n```\n\nTo pop only single elements from the stream containing ExHLS Chunks, you can use [`StreamSplit.pop/1`](https://hexdocs.pm/stream_split/StreamSplit.html#pop/1).\n\nNote: If the HLS playlist type is Live (not VoD), you can generate stream from single `ExHLS.Client` instance only once and only from the process, that created that `ExHLS.Client`. If you want to genereate more streams with Live HLS, you have to create a new `ExHLS.Client` each time.\n\n### Debugging\n\nIf you want to see more detailed logs about how `ex_hls` works, add the following line to the config file\nof your application:\n\n```elixir\nconfig :ex_hls, debug_verbose: true\n```\n\n## Copyright and License\n\nCopyright 2025, [Software Mansion](https://swmansion.com/?utm_source=git\u0026utm_medium=readme\u0026utm_campaign=ex_hls)\n\n[![Software Mansion](https://logo.swmansion.com/logo?color=white\u0026variant=desktop\u0026width=200\u0026tag=membrane-github)](https://swmansion.com/?utm_source=git\u0026utm_medium=readme\u0026utm_campaign=ex_hls)\n\nLicensed under the [Apache License, Version 2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmembraneframework%2Fex_hls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmembraneframework%2Fex_hls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmembraneframework%2Fex_hls/lists"}