# Meting: one async interface over five music platforms that each changed their APIs

> A zero dependency Node.js port of a PHP library that searches, resolves and streams from NetEase, Tencent, KuGou, Baidu and Kuwo behind a single constructor.

**metowolf/Meting** — :cake: Wow, such a powerful music API framework

- Repository: https://github.com/metowolf/Meting
- Stars: 2,201 · Forks: 550
- Language: JavaScript
- License: MIT
- Published: 2026-10-08 · Updated: 2026-10-08 · Language: en
- Canonical page: https://hysenlabs.com/projects/metowolf-meting

## One constructor and one set of method names

The library is used by picking a platform and then calling methods on one object:

```javascript
import Meting from '@meting/core';

// Initialize with a music platform
const meting = new Meting('netease'); // 'netease', 'tencent', 'kugou', 'baidu', 'kuwo'

// Enable data formatting for consistent output
meting.format(true);
```

The platform is a short string, and the five supported values are netease, tencent, kugou, baidu and kuwo. `format(true)` turns on the normalised output format, which is the switch that makes results comparable across platforms. Everything after that is a method: `search`, `song`, `album`, `artist`, `playlist`, `url`, `lyric` and `pic` for artwork, plus `site`, `cookie` and `format` for managing the instance itself.

The methods are all promise based and the README is consistent about wrapping calls in try and catch, even in its fallback example where a failed search on one platform is retried on another with `meting.site('tencent')`. For a library whose whole job is talking to five third party services, that is the correct default rather than a stylistic choice.

## The normalised record is the part worth designing around

With formatting enabled, every platform returns the same record shape, which is what makes a multi platform player possible:

```javascript
{
  "id": "35847388",
  "name": "Hello",
  "artist": ["Adele"],
  "album": "Hello",
  "pic_id": "1407374890649284",
  "url_id": "35847388", 
  "lyric_id": "35847388",
  "source": "netease"
}
```

Notice that the record does not contain a playable URL. It carries `url_id`, `pic_id` and `lyric_id`, which are platform specific identifiers you pass back to `url()`, `pic()` and `lyric()` to resolve them, along with `source` so you know which adapter answered. The identifiers are separate from the `id` even on NetEase, where they happen to hold the same value.

That indirection is not incidental. Streaming URLs from these services are signed and expire, so a URL fetched once is not a URL you can store. Keeping the lookup explicit means a caller resolves a fresh URL at play time rather than trusting a cached field.

## Zero runtime dependencies, and a build that rolls up two formats

The README's feature list claims zero external dependencies built with Node.js native modules only, and the package manifest agrees in the way that matters: the `dependencies` block is absent entirely, so nothing is installed alongside it at runtime. What is there is a `devDependencies` block with Rollup, the Babel plugin, the node resolve plugin and terser, which are build time tools rather than shipped code.

The package is `@meting/core`, currently at version 1.6.1, and it is a dual format package. `main` points at `./lib/meting.js`, `module` points at `./lib/meting.esm.js`, and an `exports` map offers `import` and `require` conditions for each. The package sets `"type": "module"` and ships only `lib/` and the licence in its `files` list, so the published tarball is the compiled output plus metadata.

Building is `npm run build`, which runs `rollup -c` against `rollup.config.js` at the repository root, with `npm run dev` adding watch mode. Tests run `npm test`, which builds first and then executes `node test/test.js`.

## A PHP library's shadow, including in the metadata

Meting began as a PHP project and this repository is the Node.js port, which the README states plainly and which explains several details that otherwise look odd.

The GitHub topics for the repository are api, music and php, even though the language of the code is JavaScript and the port has been the subject of work for years. The package manifest's `homepage` field points at the original PHP repository rather than this one. The README's related projects section links back to that original PHP version, and also points at reimplementations in other ecosystems, including a REST wrapper and a .NET version, which is the same pattern of fan ports this project itself followed.

None of that is a defect. It is the usual shape for a library whose name and API predate its language, and it is worth knowing because a reader searching for the API surface will land on the PHP documentation first.

## Where the README stops being reassuring

The Important Notes section is where the project is most honest, and it is short. Copyright compliance and respect for platform terms, the statement that music platform APIs may change without notice, the note that some features may be restricted by geography, and the reminder that each platform has its own rate limiting policy. There is a Rate Limiting section that recommends adding delays between requests, avoiding bursts, and implementing request queuing for heavy usage, with an example delay of two seconds.

Those warnings are the real operational content. The five platform adapters are calling endpoints that are not public contracts, so an adapter can stop working on a day that has nothing to do with this library's version. A caller that degrades gracefully across platforms, as the README's own error handling example does with a fallback to tencent, is better protected than one that assumes a single provider.

The related projects list is a reasonable place to look for what people build on top: a WordPress music player, an online music player, a RESTful API wrapper, and ports to .NET and other stacks.

## A quiet repository with no tagged releases

GitHub reports 2,198 stars, 549 forks and 6 open issues for this repository. The star and fork counts are close together, which fits a project that people port or vendor rather than merely depend on.

There are no GitHub releases at all, so there is no tag to pin and no published changelog entry per version. The repository was last pushed on 2026-03-29, and the package manifest is at 1.6.1, so the working version is newer than anything the release page would have told you. If you need to know what changed, `CHANGELOG.md` at the root is where to look, and `ARCHITECTURE.md` sits next to it for the internal design. There is also a `CLAUDE.md`, `rollup.config.js`, and a `test/` directory.

That combination, no releases plus a dated last push plus 2.2k stars, is the honest picture: a mature, widely used interface over upstream services that change on their own schedule. Pin the package version you test against, and verify the adapters you rely on rather than assuming the package version implies adapter freshness.

## Conclusion

Meting's value is the shape of its interface, not the longevity of any single platform integration: one constructor, one set of method names, one normalised record format, and no runtime dependencies to audit. The parts to check before depending on it are the platform adapters, because they track private endpoints that the platforms change without notice, as the README itself warns. The repository was last pushed on 2026-03-29 and ships version 1.6.1 with no GitHub releases, so read `CHANGELOG.md` and `ARCHITECTURE.md` in the repository rather than assuming npm's version number tells you how fresh the adapters are.

## FAQ

### What platforms does Meting support?

Five: NetEase Cloud Music, Tencent Music, KuGou, Baidu Music and Kuwo, selected with the short codes netease, tencent, kugou, baidu and kuwo passed to the constructor. The README's support table marks search, song, album, artist, playlist, streaming URL, lyrics and artwork as supported for all five.

### How do I get a playable song URL with Meting?

Search results return identifiers rather than a URL. Take the url_id field from the record and pass it to meting.url() along with a bitrate such as 320, and the result contains the streaming location. Identifiers are kept separate because platform URLs are signed and expire, so the lookup is meant to happen at play time rather than being cached.

### Does Meting have any npm dependencies?

At runtime, none. The published package @meting/core declares no dependencies block, and the README describes it as built with Node.js native modules only. Rollup, Babel, the node resolve plugin and terser appear as devDependencies, so they are used to build the bundle and are not installed alongside the library.

### Is Meting still being updated?

The repository was last pushed on 2026-03-29 and the package manifest is at version 1.6.1, so work is happening but slowly. There are no GitHub releases or tags to pin, which means CHANGELOG.md at the root is the version history to read. The README also warns that platform APIs may change without notice, so verify the adapters you depend on.

## Sources

- [Issues](https://github.com/metowolf/Meting/issues)
- [License: MIT](https://github.com/metowolf/Meting/blob/master/LICENSE)
- [metowolf/Meting on GitHub](https://github.com/metowolf/Meting)
- [README](https://github.com/metowolf/Meting/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/metowolf-meting
