npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kipphi-player

v2.1.2

Published

A Phigros Chart Player, designed with the philosophy of stateless-rendering. Very friendly for editors since it's high-performance.

Downloads

445

Readme

Kipphi Player - An editor-friendly Phigros Chart Player

奇谱播放器为奇谱发生器的子项目,用于在编辑器中播放Phigros谱面(RPE或KPA格式)。基于Kipphi

Kipphi Player is a subproject of Kipphi, which is a Phigros chart player for editor. Based on Kipphi.

使用

最简单用例:

import { Player, AudioProcessor, Images, Respack } from "kipphi-player";
import { Chart } from "kipphi";

await Images.loadAndOptimize({
    anchor: "Anchor.png", // 标识判定线锚点,若不需要可用全透明图片
    below: "Below.png", // 标识一个Note为判定线下方,若不需要可用全透明图片
});

// 需自备Phira格式的资源包
const respack = Respack.loadFromPhira(async (filename) => {
    // 自行实现获得资源包内文件的逻辑
    // 最简单的方法是,直接把解压好的资源包放在一个文件夹内,然后在此函数中用fetch获得它们
    return ...
})

// AudioProcessor,包装了AudioContext的对象。
// 仅打击音效用AudioContext控制,曲目播放仍然用<audio>标签播放
const audioProcessor = new AudioProcessor()
await audioProcessor.init({
    tap: "Tap.wav",
    drag: "Drag.wav",
    flick: "Flick.wav"
});
// 如果资源包里已经有音效了,可以用这个方法直接创建
const audioProcessor = AudioProcessor.fromRespack(respack);

const name = "qualia";

const audio = new Audio(`charts/${name}/music.mp3`);
// Images.loadImage要load事件触发才会完成Promise,无需担心只加载一部分的问题
const background = await createImageBitmap(await Images.loadImage(`charts/${name}/illustration.jpg`));

const canvas = document.getElementById("canvas") as HTMLCanvasElement;

// 也可以渲染RPE谱面,自己选择
const chart = Chart.fromKPAJSON(await (await fetch(`charts/${name}/chart.json`)).json());

const player = new Player(canvas, audioProcessor, audio, background);

player.receive(chart, async (textureName) => {
    // 自行实现纹理加载逻辑(在前端,需要的是Blob)
    // 不需要纹理的话返回undefined或者null即可
    return ...
})
document.onclick = () => {
    player.play();
};

// 进度、音量等可自行控制

// 打击特效的音量
player.audioProcessor.volume = 2.0;

用于后端

得益于 skia-canvas,奇谱播放器也可用于Node.js或Bun等后端运行环境。

安装后端版本:npm install kpp-renderbun add kpp-render。(其实我还没上传这个包)

在拯救者Y7000P(i7 14650,GeForce 5060)上的测试,干跑物量1000左右谱面的渲染,速度平均能有1000多fps。渲染Sildild的Singularity谱面(物量84488),平均速度30多fps。峰值内存占用约2GiB。

但是以上是干跑渲染。如果使用ffmpeg(为了在单进程中尽量零拷贝,本项目使用了 node-av)收集并合成视频,则会受到编码及封装的速度限制。本人不太会玩视频合成,无法尽可能压榨 ffmpeg 性能,欢迎优化。

export async function renderChartFast(
    chart: Chart,
    illustrationBlobOrBuffer: Blob | Buffer,
    textureFetcher: (name: string) => Promise<Buffer>,
    audioBuffer: Buffer,
    range?: [number, number]
): Promise<{
    out: Buffer;
    duration: number;
    fps: number;
}>;