{"id":13624345,"url":"https://github.com/aadsm/jsmediatags","last_synced_at":"2025-05-15T06:05:05.324Z","repository":{"id":2622390,"uuid":"46700338","full_name":"aadsm/jsmediatags","owner":"aadsm","description":"Media Tags Reader (ID3, MP4, FLAC)","archived":false,"fork":false,"pushed_at":"2024-08-13T17:30:19.000Z","size":995,"stargazers_count":776,"open_issues_count":60,"forks_count":127,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-05-11T14:18:06.611Z","etag":null,"topics":["flac","id3","mp3","nodejs","reader","tag-reader"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aadsm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":"2015-11-23T06:12:55.000Z","updated_at":"2025-04-14T06:59:05.000Z","dependencies_parsed_at":"2024-06-18T12:37:16.710Z","dependency_job_id":"16012353-614e-42bf-a0ff-c50f97b36396","html_url":"https://github.com/aadsm/jsmediatags","commit_stats":{"total_commits":240,"total_committers":24,"mean_commits":10.0,"dds":0.3458333333333333,"last_synced_commit":"b7bbcdcceeddac6f0b22f05585c66bdfbb09ee78"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aadsm%2Fjsmediatags","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aadsm%2Fjsmediatags/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aadsm%2Fjsmediatags/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aadsm%2Fjsmediatags/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aadsm","download_url":"https://codeload.github.com/aadsm/jsmediatags/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253754345,"owners_count":21958843,"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":["flac","id3","mp3","nodejs","reader","tag-reader"],"created_at":"2024-08-01T21:01:41.527Z","updated_at":"2025-05-15T06:05:05.301Z","avatar_url":"https://github.com/aadsm.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# JS MediaTags\n\nThe next version of https://github.com/aadsm/JavaScript-ID3-Reader.\n\n## Donations\nA few people have asked me about donations (or even crowdfunding). I would prefer you to consider making a donation to the [\"Girls Who Code\" NPO](https://www.classy.org/checkout/donation?eid=77372). If you do please send me a message so I can add you as a contributor.\n\n## [Contributors](https://github.com/aadsm/jsmediatags/blob/master/CONTRIBUTORS.md)\n\n## [Contributing](https://github.com/aadsm/jsmediatags/blob/master/CONTRIBUTING.md)\n\n## Current Support\n\n* File Readers\n  * NodeJS\n  * XMLHttpRequest\n  * Blob\n  * File\n  * Buffers/Arrays\n  * React Native\n* Tag Readers\n  * ID3v1\n  * ID3v2 (with unsynchronisation support!)\n  * MP4\n  * FLAC\n\n## How to use\n\n### NodeJS\n\nRun `npm install jsmediatags --save` to install.\n\n```javascript\n// Simple API - will fetch all tags\nvar jsmediatags = require(\"jsmediatags\");\n\njsmediatags.read(\"./music-file.mp3\", {\n  onSuccess: function(tag) {\n    console.log(tag);\n  },\n  onError: function(error) {\n    console.log(':(', error.type, error.info);\n  }\n});\n```\n\n```javascript\n// Advanced API\nvar jsmediatags = require(\"jsmediatags\");\n\nnew jsmediatags.Reader(\"http://www.example.com/music-file.mp3\")\n  .setTagsToRead([\"title\", \"artist\"])\n  .read({\n    onSuccess: function(tag) {\n      console.log(tag);\n    },\n    onError: function(error) {\n      console.log(':(', error.type, error.info);\n    }\n  });\n```\n\n### Browser\n\nCopy the [`dist/jsmediatags.min.js`](https://github.com/aadsm/jsmediatags/blob/master/dist/jsmediatags.min.js) file into your web application directory and include it with a script tag.\nThis library is also available on cdnjs at https://cdnjs.com/libraries/jsmediatags.\nUMD will give you multiple usage options to use it:\n\n```javascript\n// As a global Object\nvar jsmediatags = window.jsmediatags;\n```\n```javascript\n// As a CommonJS Module\nvar jsmediatags = require(\"jsmediatags\");\n```\n\nIt supports loading files from remote hosts, Blob and File objects:\n```javascript\n// From remote host\njsmediatags.read(\"http://www.example.com/music-file.mp3\", {\n  onSuccess: function(tag) {\n    console.log(tag);\n  },\n  onError: function(error) {\n    console.log(error);\n  }\n});\n```\n\nNote that the URI has to include the scheme (e.g.: https://), as relative URIs are not supported.\n\n\n```javascript\n// From Blob\njsmediatags.read(blob, ...);\n```\n```javascript\n// From File\ninputTypeFile.addEventListener(\"change\", function(event) {\n  var file = event.target.files[0];\n  jsmediatags.read(file, ...);\n}, false);\n```\n\nYou can find more about UMD usage options [here](http://www.forbeslindesay.co.uk/post/46324645400/standalone-browserify-builds).\n\n### React Native\n\nReact Native support requires some additional dependencies:\n\n```bash\nnpm install --save jsmediatags buffer react-native-fs\n```\n\nWith these dependencies installed, usage with React Native should remain the\nsame:\n\n```js\nconst jsmediatags = require('jsmediatags');\n\nnew jsmediatags.Reader('/path/to/song.mp3')\n  .read({\n    onSuccess: (tag) =\u003e {\n      console.log('Success!');\n      console.log(tag);\n    },\n    onError: (error) =\u003e {\n      console.log('Error');\n      console.log(error);\n    }\n});\n\n// Or wrap it with a promise\nnew Promise((resolve, reject) =\u003e {\n  new jsmediatags.Reader('/path/to/song.mp3')\n    .read({\n      onSuccess: (tag) =\u003e {\n        console.log('Success!');\n        resolve(tag);\n      },\n      onError: (error) =\u003e {\n        console.log('Error');\n        reject(error);\n      }\n  });\n})\n  .then(tagInfo =\u003e {\n    // handle the onSuccess return\n  })\n  .catch(error =\u003e {\n    // handle errors\n  });\n```\n\n### Articles\n\n* [Cordova : lire les metadatas des mp3s avec jsmediatags](http://blog.luce.pro/2016/02/28/Phonegap-lire-les-metadatas-des-mp3s-avec-jsmediatags/)\n\n## Documentation\n\n### The Output\nThis is an example of the object passed to the `jsmediatags.read`'s `onSuccess` callback.\n\n#### ID3v2\n```javascript\n{\n  type: \"ID3\",\n  version: \"2.4.0\",\n  major: 4,\n  revision: 0,\n  tags: {\n    artist: \"Sam, The Kid\",\n    album: \"Pratica(mente)\",\n    track: \"12\",\n    TPE1: {\n      id: \"TPE1\",\n      size: 14,\n      description: \"Lead performer(s)/Soloist(s)\",\n      data: \"Sam, The Kid\"\n    },\n    TALB: {\n      id: \"TALB\",\n      size: 16,\n      description: \"Album/Movie/Show title\",\n      data: \"Pratica(mente)\"\n    },\n    TRCK: {\n      id: \"TRCK\",\n      size: 3,\n      description: \"Track number/Position in set\",\n      data: \"12\",\n    }\n  },\n  size: 34423,\n  flags: {\n    unsynchronisation: false,\n    extended_header: false,\n    experimental_indicator: false,\n    footer_present: false\n  }\n}\n```\n\n#### MP4\n```javascript\n{\n  type: \"MP4\",\n  ftyp: \"M4A\",\n  version: 0,\n  tags: {\n    \"©too\": {\n      id: \"©too\",\n      size: 35,\n      description: 'Encoding Tool',\n      data: 'Lavf53.24.2'\n    }\n  }\n}\n```\n\n#### FLAC\n```javascript\n{\n  type: \"FLAC\",\n  version: \"1\",\n  tags: {\n    title: \"16/12/95\",\n    artist: \"Sam, The Kid\",\n    album: \"Pratica(mente)\",\n    track: \"12\",\n    picture: ...\n  }\n}\n```\n\nThe `tags` property includes all tags that were found or specified to be read.\nSince each tag type (e.g.: ID3, MP4) uses different tag names for the same type of data (e.g.: the artist name) the most common tags are also available under human readable names (aka shortcuts). In this example, `artist` will point to `TPE1.data`, `album` to `TALB.data` and so forth.\n\nThe expected tag object depends on the type of tag read (ID3, MP4, etc.) but they all share a common structure:\n\n```\n{\n  type: \u003cthe tag type: ID3, MP4, etc.\u003e\n  tags: {\n    \u003cshortcut name\u003e: \u003cpoints to a tags data\u003e\n    \u003ctag name\u003e: {\n      id: \u003ctag name\u003e,\n      data: \u003cthe actual tag data\u003e\n    }\n  }\n}\n```\n\n### Shortcuts\n\nThese are the supported shortcuts.\n\n* `title`\n* `artist`\n* `album`\n* `year`\n* `comment`\n* `track`\n* `genre`\n* `picture`\n* `lyrics`\n\n### Picture data\n\nThe `picture` tag contains an array buffer of all the bytes of the album artwork image as well as the content type of the image. The data can be converted and displayed as an image using:\n\n```javascript\nconst { data, format } = result.tags.picture;\nlet base64String = \"\";\nfor (const i = 0; i \u003c data.length; i++) {\n  base64String += String.fromCharCode(data[i]);\n}\nimg.src = `data:${data.format};base64,${window.btoa(base64String)}`;\n```\n\n### HTTP Access Control (CORS)\n\nWhen using HTTP [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) requests you need to make sure that the server is configured to receive `If-Modified-Since` and `Range` headers with the request.\nThis can be configured by returning the `Access-Control-Allow-Headers` HTTP header with the OPTIONS request response.\n\nSimilarly, you should also allow for the browser to read the `Content-Length` and `Content-Range` headers. This can be configured by returning the  `Access-Control-Expose-Headers` HTTP header.\n\nIn short, the following headers are expected:\n```\nAccess-Control-Allow-Headers: If-Modified-Since, Range\nAccess-Control-Expose-Headers: Content-Length, Content-Range\n```\n\nThis library still works without these options configured on the server. However it will download the entire file instead of only the necessary bytes for reading the tags.\n\n### File and Tag Readers\n\nThis library uses file readers (MediaFileReader API) to read the file itself and media tag readers (MediaTagReader API) to parse the tags in the file.\n\nBy default the library will automatically pick the most appropriate file reader depending on the file location. In the common case this will be the URL or local path where the file is located.\n\nA similar approach is taken for the tag reader. The most appropriate tag reader will be selected depending on the tag signature found in the file.\n\nHowever, you can specify exactly which file reader or tag reader to use using the advanced API.\n\nNew file and tag readers can be implemented by extending the MediaFileReader and MediaTagReader classes. Check the `Development` section down bellow for more information.\n\n### Reference\n\n* `jsmediatags.Reader`\n  * `setTagsToRead(tags: Array\u003cstring\u003e)` - Specify which tags to read\n  * `setFileReader(fileReader: typeof MediaFileReader)` - Use this particular file reader\n  * `setTagReader(tagReader: typeof MediaTagReader)` - Use this particular tag reader\n  * `read({onSuccess, onError})` - Read the tags.\n\n* `jsmediatags.Config`\n  * `addFileReader(fileReader: typeof MediaFileReader)` - Add a new file reader to the automatic detection system.\n  * `addTagReader(tagReader: typeof MediaTagReader)` - Add a new tag reader to the automatic detection system.\n  * `setDisallowedXhrHeaders(disallowedXhrHeaders: Array\u003cstring\u003e)` - Prevent the library from using specific http headers. This can be useful when dealing with CORS enabled servers you don't control.\n  * `setXhrTimeoutInSec(timeoutInSec: number)` - Sets the timeout time for http requests. Set it to 0 for no timeout at all. It defaults to 30s.\n\n## Development\n\nSource code uses Flow for type checking meaning that a compilation step is needed to remove all type annotations.\nWhen using this library with NodeJS you can use the runtime compilation that is supported by babel. It will be slightly slower but no compilation step is required.\n\n### NodeJS (With Runtime Compilation)\n\n```javascript\nrequire('babel-core/register');\n\nvar NodeFileReader = require('./src/NodeFileReader');\nvar ID3v2TagReader = require('./src/ID3v2TagReader');\n...\n```\n\n### NodeJS (With Compiled Code (faster))\n\nRun `npm run build` to generate proper JavaScript code into the `build2` directory.\n\n```javascript\nvar NodeFileReader = require('./build2/NodeFileReader');\nvar ID3v2TagReader = require('./build2/ID3v2TagReader');\n...\n```\n\nRun `npm run watch` to automatically recompile the source code whenever a file is changed.\n\n### Browser\n\nRun `npm run dist` to generate a UMD version of this library that is ready to be used in a browser.\n\nTwo packages are created for the browser: `dist/jsmediatags.min.js` and `dist/jsmediatags.js`. One is a minimized version that is meant to be used in production and the other a regular version meant to be used for debugging.\n\nRun `npm run dist-watch` to recompile and browserify the source code whenever a file is changed. This will only regenerate the `dist/jsmediatags.js` file.\n\n### New File Readers\n\nExtend the `MediaFileReader` class to implement a new file reader. Methods to implement are:\n\n* init\n* loadRange\n* getBytesLoaded\n* getByteAt\n\nCurrent Implementations:\n* [NodeFileReader](https://github.com/aadsm/jsmediatags/blob/master/src/NodeFileReader.js) (NodeJS)\n* [XhrFileReader](https://github.com/aadsm/jsmediatags/blob/master/src/XhrFileReader.js) (Browser and NodeJS)\n* [BlobFileReader](https://github.com/aadsm/jsmediatags/blob/master/src/BlobFileReader.js) (Blob and File)\n\n\n### New Tag Readers\n\nExtend the `MediaTagReader` class to implement a new tag reader. Methods to implement are:\n\n* getTagIdentifierByteRange\n* canReadTagFormat\n* \\_loadData\n* \\_parseData\n\nCurrent Implementations:\n* [ID3v1TagReader](https://github.com/aadsm/jsmediatags/blob/master/src/ID3v1TagReader.js)\n* [ID3v2TagReader](https://github.com/aadsm/jsmediatags/blob/master/src/ID3v2TagReader.js)\n* [MP4TagReader](https://github.com/aadsm/jsmediatags/blob/master/src/MP4TagReader.js)\n\n### Unit Testing\n\nJest is the framework used. Run `npm test` to execute all the tests.\n\n## JavaScript-ID3-Reader\nIf you want to migrate your project from [JavaScript-ID3-Reader](https://github.com/aadsm/JavaScript-ID3-Reader) to `jsmediatags` use the following guiding examples:\n\n### All tags\n**JavaScript-ID3-Reader:**\n```javascript\nID3.loadTags(\"filename.mp3\", function() {\n  var tags = ID3.getAllTags(\"filename.mp3\");\n  alert(tags.artist + \" - \" + tags.title + \", \" + tags.album);\n});\n```\n**jsmediatags:**\n```javascript\njsmediatags.read(\"filename.mp3\", {\n  onSuccess: function(tag) {\n    var tags = tag.tags;\n    alert(tags.artist + \" - \" + tags.title + \", \" + tags.album);\n  }\n});\n```\n\n### Specific tags\n**JavaScript-ID3-Reader:**\n```javascript\nID3.loadTags(\"filename.mp3\", function() {\n  var tags = ID3.getAllTags(\"filename.mp3\");\n  alert(tags.COMM.data + \" - \" + tags.TCON.data + \", \" + tags.WXXX.data);\n},\n{tags: [\"COMM\", \"TCON\", \"WXXX\"]});\n```\n**jsmediatags:**\n```javascript\nnew jsmediatags.Reader(\"filename.mp3\")\n  .setTagsToRead([\"COMM\", \"TCON\", \"WXXX\"])\n  .read({\n    onSuccess: function(tag) {\n      var tags = tag.tags;\n      alert(tags.COMM.data + \" - \" + tags.TCON.data + \", \" + tags.WXXX.data);\n    }\n  });\n```\n### Error handling\n**JavaScript-ID3-Reader:**\n```javascript\nID3.loadTags(\"http://localhost/filename.mp3\", function() {\n  var tags = ID3.getAllTags(\"http://localhost/filename.mp3\");\n  alert(tags.comment + \" - \" + tags.track + \", \" + tags.lyrics);\n},\n{\n  tags: [\"comment\", \"track\", \"lyrics\"],\n  onError: function(reason) {\n    if (reason.error === \"xhr\") {\n      console.log(\"There was a network error: \", reason.xhr);\n    }\n  }\n});\n```\n**jsmediatags:**\n```javascript\nnew jsmediatags.Reader(\"filename.mp3\")\n  .setTagsToRead([\"comment\", \"track\", \"lyrics\"])\n  .read({\n    onSuccess: function(tag) {\n      var tags = tag.tags;\n      alert(tags.comment + \" - \" + tags.track + \", \" + tags.lyrics);\n    },\n    onError: function(error) {\n      if (error.type === \"xhr\") {\n        console.log(\"There was a network error: \", error.xhr);\n      }\n    }\n  });\n```\n\n## Goals\n\n* Improve the API of JavaScript-ID3-Reader\n* Improve the source code with readable code and Flow annotated types\n* Have unit tests\n* Support NodeJS\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faadsm%2Fjsmediatags","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faadsm%2Fjsmediatags","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faadsm%2Fjsmediatags/lists"}