{"id":20604073,"url":"https://github.com/ardean/jscast","last_synced_at":"2025-04-15T02:11:23.855Z","repository":{"id":57284046,"uuid":"66441162","full_name":"ardean/jsCast","owner":"ardean","description":":radio: An Audio Streaming Application written in JavaScript","archived":false,"fork":false,"pushed_at":"2018-12-15T16:02:59.000Z","size":299,"stargazers_count":24,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T02:11:23.385Z","etag":null,"topics":["blacklist","cli","ffmpeg","icecast","javascript","jscast","json","nodejs","radio","radio-station","station","storage-types","stream","whitelist","youtube"],"latest_commit_sha":null,"homepage":"https://ardean.github.io/jsCast/","language":"JavaScript","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/ardean.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}},"created_at":"2016-08-24T07:24:13.000Z","updated_at":"2023-08-16T11:13:42.000Z","dependencies_parsed_at":"2022-09-10T09:02:06.355Z","dependency_job_id":null,"html_url":"https://github.com/ardean/jsCast","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardean%2FjsCast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardean%2FjsCast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardean%2FjsCast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ardean%2FjsCast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ardean","download_url":"https://codeload.github.com/ardean/jsCast/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248991557,"owners_count":21194894,"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":["blacklist","cli","ffmpeg","icecast","javascript","jscast","json","nodejs","radio","radio-station","station","storage-types","stream","whitelist","youtube"],"created_at":"2024-11-16T09:20:32.828Z","updated_at":"2025-04-15T02:11:23.839Z","avatar_url":"https://github.com/ardean.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jsCast\n\n[![NPM Version][npm-image]][downloads-url] [![NPM Downloads][downloads-image]][downloads-url]\n\n**An Audio Streaming Application written in JavaScript**\n\n- _storage types / API_\n- _input (item) types / API_\n- _plugin types / API_\n- _CLI support_\n  - _whitelist / blacklist_\n\n![jsCast - Web](docs/images/jsCast-Web.png)\n\n## Quick Start\n\n### Using CLI\n\nInstall jsCast globally:\n\n```sh\n$ npm i -g jscast\n```\n\nUse the new command to start an instance:\n\n```sh\n$ jsCast\n```\n\n- override default port: `-p PORT` / `--port PORT`\n- change storage type: `-s TYPE` / `--storage-type TYPE`\n- set active plugins: `-t TYPE1,TYPE2` / `--plugin-types TYPE1,TYPE2`\n- ffmpeg binary path: `--ffmpeg-path PATH`\n- initial youtube items - fillable storage types **only**: `--youtube-items URL1,URL2`\n- whitelist: `--whitelist COUNTRY1,COUNTRY2`\n- blacklist: `--blacklist COUNTRY3,COUNTRY4`\n\n### Using Script\n\n```javascript\nimport jsCast from \"jscast\";\nimport { log } from \"util\";\n\nconst instance = jsCast().on(\"clientRejected\", (client) =\u003e {\n  log(`client ${client.ip} rejected`);\n});\n\nconst icyServer = instance.pluginManager.getActiveType(\"IcyServer\");\nconst webClient = instance.pluginManager.getActiveType(\"WebClient\");\n\ninstance.station\n  .on(\"play\", (item, metadata) =\u003e {\n    log(`playing ${metadata.options.StreamTitle}`);\n  })\n  .on(\"nothingToPlay\", (playlist) =\u003e {\n    if (!playlist) {\n      log(\"no playlist\");\n    } else {\n      log(\"playlist is empty\");\n    }\n  });\n\ninstance\n  .start({\n    port: 8000,\n    allow: (client) =\u003e {\n      return true; // allow this client\n    }\n  })\n  .then(() =\u003e {\n    log(`jscast is running`);\n\n    if (icyServer) {\n      icyServer\n        .on(\"clientConnect\", (client) =\u003e {\n          log(`icy client ${client.ip} connected`);\n        })\n        .on(\"clientDisconnect\", (client) =\u003e {\n          log(`icy client ${client.ip} disconnected`);\n        });\n\n      log(`listen on http://localhost:${icyServer.port}${icyServer.rootPath}`);\n    }\n\n    if (webClient) {\n      log(`Web Client on http://localhost:${webClient.port}${webClient.rootPath} your playlists and items`);\n    }\n  })\n  .catch((err) =\u003e console.error(err));\n```\n\n## Prerequisites\n\nfirst of all install [NodeJS](https://nodejs.org/), jscast is based on it.\n\njscast uses [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg#prerequisites) as dependency so ffmpeg **needs** to be installed on your system.\n\n## Installation\n\nAs dependency:\n\n```sh\n$ npm install jscast\n```\n\nPlay around and contribute to the project:\n\n```sh\n$ git clone https://github.com/ardean/jsCast\n$ cd jsCast\n$ npm i\n$ npm start\n```\n\n## Plugin Types\n\n### Web Client\n\n**Web Client** is a `webapp` to control jsCast playlists and items. the route is `/web` by default. At the moment there is just a `YouTube` type implemented but the idea is to `control` everything with this `webapp`. There is also a `player` (using a audio tag) embedded to `play` the `SHOUTcast output`, however for me this worked only with a `Desktop-Browser`. god knows why...\n\n### IcyServer\n\nThe **IcyServer**'s task is to send the `SHOUTcast data` (received from the Station) to the `clients`. the route is `/` by default.\n\n### Speaker\n\nThis Plugin outputs the current track to the speakers.\n\n## Station\n\nThe **Station** is the core class which controls the `Stream` with his `data` and whatever currently is playing.\n\n## Item Types\n\nBuilt-in item types:\n\n- **File** gets audio files from the filesystem using the `filename` option\n- **YouTube** fetches the audio data and info from YouTube using an `url` option\n- Use **Stream** to hand over a Readable Stream object with the `stream` option\n\n[more](#custom-items) item types\n\n## Storage Types\n\nBuilt-in storage types:\n\n- **JSON** creates a folder with a json file per playlist, filename is the `playlist id`\n- **Memory** stores playlists in memory, so `changes will be lost` on shutdown\n\nIf thats not enough, you can create [your own one](#custom-storages)\n\n## Examples\n\n### Custom Items\n\njsCast has playlists with [typed items](#item-types). You can easily add your own item type:\n\n```javascript\nimport fs from \"fs\";\nimport { default as jsCast, Item } from \"jscast\";\nimport { log } from \"util\";\n\nclass MyItemType {\n  constructor() {\n    this.streamNeedsPostProcessing = true; // indicates if stream should be post processed to mp3\n  }\n\n  getStream(item, done) {\n    // get stream code...\n    log(item.type); // MyItem\n    done \u0026\u0026 done(err, stream);\n  }\n\n  getMetadata(item, done) {\n    // get metadata code...\n    log(item.options.myProp); // myValue\n    done \u0026\u0026 done(err, {\n      StreamTitle: \"my title\"\n    });\n  }\n}\n\nItem.registerType(\"MyItem\", new MyItemType());\n\njsCast({\n  stationOptions: {\n    storageType: \"Memory\",\n    playlists: [{\n      type: \"MyItem\",\n      options: {\n        myProp: \"myValue\"\n      }\n    }, {\n      type: \"YouTube\",\n      options: {\n        url: \"https://www.youtube.com/watch?v=hhHXAMpnUPM\"\n      }\n    }, {\n      type: \"Stream\",\n      options: {\n        title: \"A cool audio stream!\",\n        stream: fs.creadReadStream(\"./sound.mp3\")\n      }\n    }, {\n      type: \"File\",\n      options: {\n        title: \"NICE TRACK!\",\n        filename: \"./myTrack.mp3\"\n      }\n    }]\n  }\n})\n.start()\n.catch((err) =\u003e console.error(err));\n```\n\n### Custom Storages\n\nYou can use the built-in [storage types](#storage-types) or create your own one:\n\n```javascript\nimport { default as jsCast, Storage } from \"jscast\";\n\nclass MyStorageType {\n  constructor() {\n    this.isFillable = true; // indicates that this type can be pre filled on init\n  }\n\n  activate(options, done) {\n    // initialize code...\n    done \u0026\u0026 done(err);\n  }\n\n  fill(playlists, done) {\n    // fill storage from playlists option in Server and Station class\n    done \u0026\u0026 done(err);\n  }\n\n  findAll(done) {\n    // findAll code...\n    done \u0026\u0026 done(err, playlists);\n  }\n\n  insert(playlist, done) {\n    // insert code...\n    done \u0026\u0026 done(err);\n  }\n\n  update(playlist, done) {\n    // update code...\n    done \u0026\u0026 done(err);\n  }\n\n  remove(playlistId, done) {\n    // remove code...\n    done \u0026\u0026 done(err);\n  }\n}\n\nStorage.registerType(\"MyStorage\", new MyStorageType());\n\njsCast({\n  stationOptions: {\n    storageType: \"MyStorage\"\n  }\n})\n.start()\n.catch((err) =\u003e console.error(err));\n```\n\n## TODO\n\n- API Documentation\n- Authentication\n- Change async to Promise\n\n## License\n\n[MIT](LICENSE)\n\n[downloads-image]: https://img.shields.io/npm/dm/jscast.svg\n[downloads-url]: https://npmjs.org/package/jscast\n[npm-image]: https://img.shields.io/npm/v/jscast.svg\n[npm-url]: https://npmjs.org/package/jscast\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fardean%2Fjscast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fardean%2Fjscast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fardean%2Fjscast/lists"}