BBPlayer treats a Bilibili account as a music library, not a video app
一款简约、好用的 BiliBili 音乐播放器。
At a glance
- What is it?
- BBPlayer is a React Native and Expo player for Bilibili audio, with local-first storage, SPL lyrics and a monorepo that splits the app, a Cloudflare Worker backend and shared packages. It suits Android listeners who want their own playlists, and it is not a general purpose music client.
- Who is it for?
- BBPlayer suits an Android user who is a core Bilibili listener, wants a lightweight player instead of the official client, and expects to sign in with their own account by QR code, SMS code or a pasted cookie.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The account is the content source, so login comes first
BBPlayer is a React Native and Expo application for listening to audio hosted on Bilibili, and its whole model follows from that. There is no separate catalogue and no independent streaming backend. The library is your Bilibili account, which is why the README leads with three login routes: scanning a QR code, entering a phone number with an SMS verification code, or setting a cookie by hand.
Once signed in, the available sources widen. You can add local playlists, and you can reach your own favourites and subscribed collections directly. The README also describes an import path that takes a playlist from NetEase Cloud Music or QQ Music and automatically matches it to Bilibili videos, saving the result as a playlist. That is a conversion rather than a connection, which matters for expectations: those services are not being streamed from, their track lists are being located in Bilibili's own library.
Search is the other half of the source story, and it is tailored to Bilibili's identifiers. The search supports BV and AV numbers and resolves b23.tv short links, and it can also search inside your favourites and inside a local playlist. For a listener whose habits are built around Bilibili, that is the difference between a useful search box and a generic one that never finds the right track.
Playback features that go past a plain audio player
The player core lists play and pause, loop, shuffle, a play queue, loudness equalisation, resume from the last position, and automatic playback on launch. Several of these are the kind of detail that separates a serious player from a demo.
Loudness equalisation is the one with the clearest reason to exist. Audio pulled from a video platform is uploaded by many different people at many different levels, so a fixed volume setting produces a playlist where some tracks are quiet and some are loud. Equalising the level across sources is the fix, and it is the feature a listener notices within a day of switching.
Downloads are handled with a simple download manager, and cached songs can be exported as .m4a files to local storage with cover art, metadata and embedded lyrics. The export detail is what makes the feature useful outside the app: a cached file that only plays inside BBPlayer is a cache, whereas a tagged .m4a with lyrics is a file that survives the app being uninstalled. Around the edges sit a sleep timer and play history statistics shown as a leaderboard.
SPL lyrics, word-level timing and a floating desktop window
The lyrics system is where this project puts real engineering effort, and it is built on a specification the project publishes as SPL. The README states support for per-character progress, romanised annotation and translated lyrics, which is a level of detail that most players do not attempt.
Per-character progress is what makes a lyric line fill in as it is sung rather than appearing as a completed block. Romanisation and translation are separate display layers, so a line can carry the original text, a romanised reading of it and a translation at the same time, which matters for listeners following a language they do not read fluently.
Getting the text is handled in three ways: automatic matching against NetEase, QQ and Kugou lyrics, manual search, or pasting LRC or SPL text directly with an offset adjustment for the case where the timing drifts. Display options include desktop lyrics in a floating window and lyrics in the status bar, and the same line-by-line model works for the classic LRC format, so existing lyric sources are still usable.
This is the area where the project differs most from a stock player, and it is also the area a reviewer should test first, because the per-character data depends on the lyric source rather than on the app.
A pnpm monorepo with a Worker backend and eight shared packages
The repository layout is a pnpm workspace, and the root package.json declares it explicitly:
"workspaces": [
"apps/*",
"apps/*/web",
"packages/*",
"packages/*/example"
],The apps directory holds the mobile application, a backend described as a Cloudflare Worker that provides playlist sharing and update queries, a documentation site, and a tool for publishing updates. The packages directory holds the shared libraries, and two of them carry most of the weight. @bbplayer/orpheus is the audio playback engine built on Media3, and @bbplayer/splash is the lyrics parsing and conversion core. The rest are smaller: an eslint plugin with project specific lint rules, a logging library, an image theme colours package that extracts colours from cover art, a native capabilities integration module, an SVG based date heatmap component, and an Expo module wrapping a Jetpack Compose WavySlider.
The application stack is React Native with Expo, Zustand for state, React Query for data requests, Material Design 3 through React Native Paper and Expo UI, and Drizzle ORM for the database. Drizzle is worth noting for anyone who cares about the local-first claim, because a local-first app still needs a schema, and the ORM is where that schema lives.
One piece of the architecture is easy to miss. The backend Worker is not optional decoration. Playlist sharing and the update query both need a server, so an offline app is really an offline client, with a small server attached for the two features that inherently require one.
pnpm scripts that show how the project is maintained
The root package.json is where the toolchain discipline of the project shows. It is a private root package, and it pins the package manager:
"packageManager": "[email protected]"The scripts cover dependency hygiene, formatting, linting, type checking, git hooks and update publishing:
"scripts": {
"check:deps": "syncpack lint --dependency-types dev,prod,peer,overrides",
"fix:deps": "syncpack fix --dependency-types dev,prod,peer,overrides",
"format": "oxfmt --write .",
"lint": "oxlint --type-aware",
"lint:fix": "oxlint --type-aware --fix",
"postinstall": "lefthook install",
"publish:update": "pnpm --filter @bbplayer/update-publisher start",
"type-check": "tsgo --build --noEmit"
},A few of these are unusual enough to be worth decoding. syncpack is used to lint and fix dependency version mismatches across the workspace, which is the kind of check a monorepo needs once the same package exists in several versions. The linter is oxlint run in type-aware mode rather than ESLint, with the project's own plugin loaded through the oxlint jsPlugins route. The type checker is tsgo, the native preview build of the TypeScript compiler, run with build and noEmit. And postinstall installs lefthook, which is why a lefthook.yml and a mise.toml sit in the repository root alongside the oxlint and syncpack configuration files.
The pattern is a workspace that treats its own consistency as a build concern. A contributor cloning the monorepo inherits all of it at install time.
iOS is admitted to be out of step, and analytics ship by default
Two limitations deserve to be read carefully rather than skimmed, because both are stated plainly by the project itself.
The first is platform support. The README says plainly that iOS received some basic adaptation in the past, but that the focus remains on Android, that iOS is not developed in step, and that there is no guarantee it compiles successfully. The practical reading is that BBPlayer is an Android application with an iOS target that is best effort.
The second is telemetry. The app embeds Firebase Analytics and Sentry. The README describes two categories: usage data, meaning feature usage frequency and playback session duration, and crash reports, meaning stack traces at the point of a crash. The privacy commitments are that the data contains no personal identifying information, that nothing related to account privacy is collected such as cookie contents or detailed browsing history, and that the statistics code is open source and visible. There is also a control: a share data switch for crash reports and anonymous statistics that can be turned off at any time in the general settings, which stops the upload entirely.
That is a defensible position for a free app, and the opt-out makes it workable, but a reader should know the default is on before installing rather than discovering it in a settings screen afterwards. The repository also carries a PRIVACY.md file, and the top-level entries include a gitleaks configuration and baseline, which is consistent with a project that takes secret handling seriously.
An MIT licence, a dev branch, and a donation-funded maintainer
The licence is MIT, which is about as permissive as software licences get and raises no particular question for adopters. The repository ships a LICENSE file at the top level, and the README states the choice explicitly.
The default branch is dev rather than main, which matters for anyone cloning or forking. Development therefore happens on the default branch, and the published releases come from tagged builds: v2.7.0 on 2026-09-26, v2.6.5 on 2026-09-08 and v2.6.4 on 2026-08-11. The last push was recent, so the project is being worked on rather than sitting still, and the release cadence is monthly rather than daily.
The project also makes its lineage explicit, crediting AzusaPlayer, BiliSound and Salt Player for inspiration, along with Spotify and, as the source of the content itself, Bilibili. That list is a useful pointer for anyone evaluating alternatives: these are the players and the ideas BBPlayer was built from, and each takes a different route into the same problem of playing Bilibili audio away from the official client.
Sustaining the work is a matter of donations rather than a paid tier, and the README is frank about where the money goes, describing the funds as covering a meal for the maintainer or the purchase of a galgame. WeChat Pay and Alipay are the two options listed.
Editorial conclusion
BBPlayer suits an Android user who is a core Bilibili listener, wants a lightweight player instead of the official client, and expects to sign in with their own account by QR code, SMS code or a pasted cookie. It is the wrong tool for an iOS-only household, because the project states that iOS is not kept in step and does not guarantee the app compiles there, and it is the wrong tool for anyone who wants NetEase or QQ playback to be independent of Bilibili, since the import path matches those playlists to Bilibili videos rather than streaming from those services. Before you adopt it, check the app on the device you actually own, decide whether the anonymous analytics and crash reporting that ship with Firebase Analytics and Sentry are acceptable given the opt-out switch in the general settings, and read the MIT licence file, since the code is permissive but the Bilibili content it plays is governed by the service you sign in to.
Frequently asked questions
How do I sign in to BBPlayer with a Bilibili account?
The README lists three ways: scanning a QR code, entering a phone number with an SMS verification code, or setting the cookie manually. Once signed in you can reach your favourites and subscribed collections directly as well as adding local playlists.
Does BBPlayer play NetEase Cloud Music or QQ Music directly?
It does not stream from those services. The import feature takes a playlist from NetEase Cloud Music or QQ Music and automatically matches the tracks to Bilibili videos, then saves the result as a playlist in the app.
Is there a build of BBPlayer for iOS?
The README says iOS received basic adaptation earlier but that the focus remains on Android, that iOS is not developed in step, and that compilation is not guaranteed to succeed there.
What data does BBPlayer collect, and can it be turned off?
The app integrates Firebase Analytics and Sentry for usage data such as feature usage frequency and playback session duration, plus crash stack traces. The data is described as anonymous and excludes account privacy information, and the share data switch in the general settings stops the upload.
Can I export songs from BBPlayer to files on my device?
Yes. Cached songs can be exported as .m4a files to local storage with cover art, metadata and embedded lyrics, in addition to the download manager that supports offline playback inside the app.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bbplayer-app-bbplayer)Was this useful?