{"id":13893780,"url":"https://github.com/ghaiklor/icecast-parser","last_synced_at":"2025-05-01T09:55:00.096Z","repository":{"id":39618221,"uuid":"50835871","full_name":"ghaiklor/icecast-parser","owner":"ghaiklor","description":"Node.js module for getting and parsing metadata from SHOUTcast/Icecast radio streams","archived":false,"fork":false,"pushed_at":"2024-07-05T08:39:13.000Z","size":1236,"stargazers_count":72,"open_issues_count":2,"forks_count":18,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-01T09:54:31.631Z","etag":null,"topics":["icecast","icecast-parser","metadata","nodejs","parse","radio-station","radio-stream","shoutcast"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/ghaiklor.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2016-02-01T11:44:22.000Z","updated_at":"2025-04-18T16:36:28.000Z","dependencies_parsed_at":"2024-06-18T22:59:22.102Z","dependency_job_id":"de85354c-a834-4fc3-9d74-63c5aa556a13","html_url":"https://github.com/ghaiklor/icecast-parser","commit_stats":{"total_commits":243,"total_committers":9,"mean_commits":27.0,"dds":0.5637860082304527,"last_synced_commit":"3cc15d89948c779654e6b292152dbe1168c36e25"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaiklor%2Ficecast-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaiklor%2Ficecast-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaiklor%2Ficecast-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaiklor%2Ficecast-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghaiklor","download_url":"https://codeload.github.com/ghaiklor/icecast-parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251856993,"owners_count":21655119,"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":["icecast","icecast-parser","metadata","nodejs","parse","radio-station","radio-stream","shoutcast"],"created_at":"2024-08-06T18:01:17.045Z","updated_at":"2025-05-01T09:55:00.063Z","avatar_url":"https://github.com/ghaiklor.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# icecast-parser\n\n[![Build Status](https://travis-ci.com/ghaiklor/icecast-parser.svg?branch=master)](https://travis-ci.com/ghaiklor/icecast-parser)\n[![Code Coverage](https://codecov.io/gh/ghaiklor/icecast-parser/branch/master/graph/badge.svg)](https://codecov.io/gh/ghaiklor/icecast-parser)\n\n[![GitHub followers](https://img.shields.io/github/followers/ghaiklor?label=Follow\u0026style=social)](https://github.com/ghaiklor)\n[![Twitter Follow](https://img.shields.io/twitter/follow/ghaiklor?label=Follow\u0026style=social)](https://twitter.com/ghaiklor)\n\nNode.js module for getting and parsing metadata from SHOUTcast/Icecast radio streams.\n\n*NOTE: the server that serves radio station stream must support `Icy-Metadata` header. If that is not the case, this parser cannot parse the metadata from there.*\n\n## Features\n\n- Opens async connection to URL and gets response with radio stream and metadata. Then pipes the response to `Transform` stream for processing;\n- Getting metadata from stream is implemented as `Transform` stream, so you can pipe it to another Writable\\Duplex\\Transform;\n- Once it receives metadata, `metadata` event triggers with metadata object;\n- After metadata is received, connection to radio station closes automatically, so you will not spend a lot of traffic;\n- But you can set `keepListen` flag in configuration object and continue listening radio station;\n- Auto updating metadata from radio station by interval in economical way (connection is opens when time has come);\n- Metadata parsed as a `Map` with key-value;\n- When you create a new instance, you get `EventEmitter`. So you can subscribe to other events;\n- Easy to configure and use;\n\n## Getting Started\n\nYou can install icecast-parser from npm.\n\n```shell\nnpm install icecast-parser\n```\n\nGet your first metadata from radio station.\n\n```typescript\nimport { Parser } from 'icecast-parser';\n\nconst radioStation = new Parser({ url: 'https://live.hunter.fm/80s_high' });\nradioStation.on('metadata', (metadata) =\u003e process.stdout.write(`${metadata.get('StreamTitle') ?? 'unknown'}\\n`));\n```\n\n## Configuration\n\nYou can provide additional parameters to constructor:\n\n- `url` - by default empty and **REQUIRED**. Otherwise, you will get an error.\n- `userAgent` - by default `icecast-parser`.\n- `keepListen` - by default `false`. If you set to `true`, then response from radio station will not be destroyed and you can pipe it to another streams. E.g. piping it to the `speaker` module.\n- `autoUpdate` - by default `true`. If you set to `false`, then parser will not be listening for recent updates and immediately close the stream. So that, you will get a metadata only once.\n- `notifyOnChangeOnly` - by default `false`. If you set both `autoUpdate` and `notifyOnChangeOnly` to `true`, it will keep listening the stream and notifying you about metadata, but it will not notify if metadata did not change from the previous time.\n- `errorInterval` - by default 10 minutes. If an error occurred when requesting, the next try will be executed after this interval. Works only if `autoUpdate` is enabled.\n- `emptyInterval` - by default 5 minutes. If the request was fullfiled but the metadata field was empty, the next try will be executed after this interval. Works only if `autoUpdate` is enabled.\n- `metadataInterval` - by default 5 seconds. If the request was fullfiled and the metadata was present, the next update will be scheduled after this interval. Works only if `autoUpdate` is enabled.\n\n```typescript\nimport { Parser } from 'icecast-parser';\n\nconst radioStation = new Parser({\n  autoUpdate: true,\n  emptyInterval: 5 * 60,\n  errorInterval: 10 * 60,\n  keepListen: false,\n  metadataInterval: 5,\n  notifyOnChangeOnly: false,\n  url: 'https://live.hunter.fm/80s_high',\n  userAgent: 'Custom User Agent',\n});\n\nradioStation.on('metadata', (metadata) =\u003e process.stdout.write(`${metadata.get('StreamTitle') ?? 'unknown'}\\n`));\n```\n\n## Events\n\nYou can subscribe to following events: `end`, `error`, `empty`, `metadata`, `stream`.\n\n- `end` event triggers when connection to radio station was ended;\n- `error` event triggers when connection to radio station was refused, rejected or timed out;\n- `empty` event triggers when connection was established successfully, but the radio station doesn't have metadata in there;\n- `metadata` event triggers when connection was established successfully and metadata is parsed;\n- `stream` event triggers when response from radio station returned and successfully piped to `Transform` stream.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghaiklor%2Ficecast-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghaiklor%2Ficecast-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghaiklor%2Ficecast-parser/lists"}