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

@taotao-lib/opensheetmusicdisplay

v1.0.4

Published

An open source JavaScript engine for displaying MusicXML based on VexFlow.

Readme

npm(本 fork 发布页): https://www.npmjs.com/package/@taotao-lib/opensheetmusicdisplay

OpenSheetMusicDisplay (OSMD)

A MusicXML renderer for the Browser

opensheetmusicdisplay.org Gitter Appveyor Build status Commitizen friendly

About OSMDDemoKey FeaturesLimitationsHow to Use OSMDSponsor OSMDAbout UsGet In Touch

:star: - Star us on Github - It really helps us a lot! :pray: - Become our Sponsor - Support our work and receive awesome perks!

Upstream Source and Local Changes

This repository is based on the upstream OpenSheetMusicDisplay project: https://github.com/opensheetmusicdisplay/opensheetmusicdisplay.

For modifications made in this local fork, see the section Fork downstream changes at the end of this README (the previously referenced LOCAL_CHANGES_SUMMARY.md is not maintained separately).

About OSMD

OpenSheetMusicDisplay renders MusicXML sheet music in the browser. It is the missing link between MusicXML and VexFlow. Built upon many years of experience in both sheet music interactivity and engraving, it is the perfect solution for app developers seeking to build digital sheet music services.

MusicXML is the de facto standard for exchanging sheet music between music software. VexFlow is widely used for rendering sheet music. It features an extensive library of musical elements, but each measure and symbol has to be created and positioned by hand in Javascript.

OpenSheetMusicDisplay brings the two together and offers an open source turnkey solution for your digital sheet music project.

Demo

Try the Public Demo to see what OSMD can do. Learn more about the demo and OSMD in the OSMD Wiki.

Developers can also run a local development demo (see Wiki):

Key Features

  • Displays MusicXML sheet music in a browser(less) environment (Javascript, Typescript, server-side: browserless NodeJS script)
  • Soon: Audio Playback (work in progress, early access build available for Github sponsors)
  • Uses Vexflow for rendering and (partly) layout
  • Parses most MusicXML tags and integrates it into an accessible and modifiable data model (e.g. to change a note's color)
  • Offers many options (OSMDOptions / EngravingRules): Page Format, Font Family, Positioning, not rendering certain elements like the title or lyrics, etc.
  • Allows modification of the displayed score, like hiding parts or instruments, hiding instrument names, title or composer, a more compact layout, or coloring notes
  • Outputs SVG or PNG, also via nodejs script in the command line, completely browserless (e.g. for server-side rendering)
  • Written in Typescript with complete type information, 100% compatible with Javascript (minified build is .js)
  • Can display tablature (guitar tabs) from MusicXML, including effects like bends and glissandi. Can be combined with treble clef.

Limitations

Not all MusicXML tags are (fully) supported:

  • Pedal marks (currently in early access for sponsors)
  • Glissando lines
  • Wavy-line (currently in early access for sponsors)
  • Etc, see OSMD 1.0 Project

Also, OSMD is a renderer, not an interactive sheet music editor. Rendering takes some time, and you can't easily/quickly move notes, place new notes, etc. (You can, however, manipulate the SVG nodes for instant changes like note re-coloring, see Exploring the Demo | Wiki)

How to Use OSMD

Sponsor OSMD and get early access to the audio player and more

It would be great if free software were sustainable on its own. But to keep on improving and developing OpenSheetMusicDisplay we need your support. Your monthly sponsorship subscription - especially if you are already actively using OSMD - would mean everything to us - it’s a stable way of enabling us to continue our work, and improve and expand OSMD. Features already available in early access:

  • OSMD Audio Player
  • Native modules + example projects (React Native, Kotlin/Android, Swift/iOS) - NEW!
  • Jianpu Display (Numbered Musical Notation), with playback

Features in the making, potentially available in future:

  • Annotations (Add custom text, music symbols, etc. to the score and export to and import from XML)
  • and more (we're always working on OSMD improvements or additional features, just look at our release history / changelog!)

Besides the early access features, you can get other perks like a personal postcard from the team in Vienna. Check them out at our GitHub sponsors page.

And there are other ways to contribute to the community - we plan on starting a blog and newsletter, and sharing our knowledge. We encourage our sponsors to bring up their desired features and pitch blog post ideas.

Though we highly recommend the sponsor route, you can also donate via Paypal:

paypal Any support is highly appreciated.

About Us

OSMD is made by Phonicscore - a music-tech company based in Vienna. We create solutions for musicians, sheet music publishers, app developers, music stores and researchers:

Our mission is to provide state of the art software solutions for building MusicXML apps and to include the community in a constant thrive for improvement. We want to take away the pain of building music software from scratch and offer a shortcut when it comes to building your next MusicXML sheet music application.

We also want to thank our Github Contributors, who show that with open source many people come together to not only share but improve software.

Get In Touch

To contact us directly, you can:


Fork downstream changes

(本段为 二次开发说明,中文撰写。)本仓库在 OpenSheetMusicDisplay 上游基础上做了 与宿主乐谱应用(如 five-line-staff)对接 的扩展:在 分页渲染完成后 暴露「每页对应哪些全局小节」以及「每页内各小节在版面上的水平区间」,用于 视口点击 / 标注锚点 / 导出 MusicXML 时与屏上谱面一致,避免仅用「总页数均分全曲小节」导致的错位。

1. 新增类型(src/OpenSheetMusicDisplay/

| 文件 | 说明 | |------|------| | PageMeasureListIndexBounds.ts | OsmdPageMeasureListIndexBounds:单页上 measureListIndex 的闭区间 [startMeasureListIndex, endMeasureListIndex](0-based,与 SourceMeasure.measureListIndex 一致)。 | | PageMeasureHorizontalLayout.ts | OsmdMeasureHorizontalSpan(单小节 measureListIndex + left/right 绘图坐标)、OsmdPageMeasureHorizontalLayout(单页 + 该页上所有不重复小节的 span 列表,已按从左到右排序)。 |

包入口 src/OpenSheetMusicDisplay/index.tsexport * 上述模块,发布构建后消费方可从 @taotao-lib/opensheetmusicdisplay 引用类型。

2. OpenSheetMusicDisplay 新增公开方法

getPageMeasureListIndexBounds(): OsmdPageMeasureListIndexBounds[]

  • 时机:在 load()render() 完成之后调用。
  • 语义:对每个已绘制的 GraphicalMusicPage,统计该页上出现的所有图元小节的 measureListIndex 的最小值与最大值(含多声部同一小节)。
  • 顺序:与 GraphicalMusicSheet.MusicPages 一致;受 EngravingRules.MaxPageToDrawNumber 约束,超出页不再输出。
  • 失败行为:若某一页无法得到有效 min/max,整表返回 [](与上游保守策略一致);宿主应仅在「返回数组长度与自身分页 HTML 页数一致」时使用。

getPageMeasureHorizontalLayouts(): OsmdPageMeasureHorizontalLayout[]

  • 时机:同上,须在 render() 之后。
  • 语义:对每一分页,按 measureListIndex 去重;同一小节多行谱表取所有 GraphicalMeasure水平并集min(left)max(right))。
  • 坐标:与排版后 BoundingBox 一致,使用公开 getter:AbsolutePosition.x + BorderLeft / + BorderRight不得访问受保护的 borderLeft / borderRight 字段)。对左右边界做 Math.min / Math.max 规范化,避免极端情况下左右颠倒。
  • 失败行为:若某一页没有任何可统计小节,整表返回 [];宿主同样应用「长度与页数一致」才采纳。
  • 宿主侧对齐:典型用法是将 left/right该页根 SVG 的 getBBox() 做线性归一化,使 0–1 横坐标与「墨迹宽度」参照一致(详见 five-line-staff 中 renderMusicXmlWithOsmdPages / pageMeasureInkNormSpans 逻辑)。

3. 与上游的关系

  • 未改动 MusicXML 解析与 VexFlow 绘制主流程;仅增加 只读查询 API 与类型导出。
  • 若未来合并上游大版本,需重点解决冲突的文件主要是:OpenSheetMusicDisplay.tsindex.ts 及上述两个类型文件。

4. 版本与发布

  • 携带上述 API 的 fork 版本以 package.jsonversion 为准(例如 1.0.3 起包含 getPageMeasureHorizontalLayouts)。
  • 发布 npm 前请执行项目内 npm run build,确保 build/(及类型声明 .d.ts)包含新导出,否则 TypeScript 消费方无法识别新 API。

5. 已知限制

  • 水平区间依赖当前 SVG/Canvas 后端 与排版结果;若宿主使用与 OSMD 渲染时不同的缩放或重新套版,需自行重新换算或重新 render() 后再取布局。
  • getPageMeasureHorizontalLayoutsgetPageMeasureListIndexBounds 在「单页数据异常」时均可能返回 空数组;宿主 不可 在长度不匹配时退而误用「全曲按页均分」而不加校验,否则会回到旧有锚点偏差问题。

已修复问题:Slur 渲染 NaN 导致 SVG path 报错

现象

打开含有圆滑连线(slur)的 MusicXML 文件(如 春之声1-音乐学院带有标记_1778326139378.musicxml)时,浏览器控制台大量报错:

Error: <path> attribute d: Expected number, "…54.523833824256CNaN NaN,NaN NaN,…".

即 OSMD 生成的 SVG <path> 元素的 d 属性中出现了 NaN,导致连线图形无法正常渲染,控制台刷屏报错。

出错元素

Slur(圆滑连线)。该文件由 Sibelius 导出,包含多段 slur 标注(<slur type="start" orientation="over"/> / <slur type="stop" orientation="over"/>)。OSMD 在计算 slur 贝塞尔曲线控制点时,某些边界条件下触发除零错误,导致控制点坐标变为 NaN,最终经 SvgVexFlowBackend.renderCurve() 写入 SVG path 的 d 属性。

根因分析

NaN 的产生链路如下:

斜率计算 (x÷0 → NaN)
  → Math.atan(NaN) → 角度 (NaN)
    → Math.cos/sin(NaN) → 控制点坐标 (NaN)
      → bezierStartPt / bezierEndPt / bezierCurveTo(…)
        → SVG path d 属性中包含 "CNaN NaN"

具体触发点在 GraphicalSlur.ts 中:

| 位置 | 问题描述 | |------|----------| | calculateMaxLeftSlope | 坐标变换后起点为 (0, 0),若天际线某点的 x === 0,则 points[i].y / points[i].x 得到 0/0 = NaN | | calculateMaxRightSlope | 若某点 x === end2.x,则 (y - points[i].y) / (end2.x - points[i].x) 分母为零产生 NaN | | Math.atan (第149行 / 第322行) | 当 endX === startX 时,(endY - startY) / 0 若分子也为 0 则 0/0 = NaN | | calculateHeightWidthRatio | 当 endX === 0max === 00/0 = NaN | | calculateAngles | 上游 NaN 斜率传入 Math.atan(NaN) 进一步传播 |

修改的文件

1. src/MusicalScore/Graphical/GraphicalSlur.ts

6 处修复

| 方法 | 修复方式 | |------|----------| | calculateMaxLeftSlope | 对每个天际线点,若 denominator = points[i].x - x 的绝对值小于 1e-5 则跳过;终点分母同样加保护 | | calculateMaxRightSlope | 同上:对每个点检查 x - points[i].x 是否接近零,起点分母同样加保护 | | Math.atan (Above 分支, ≈149行) | 显式检查 endXStartXDifference !== 0,为零时直接取 ±π/2 | | Math.atan (Below 分支, ≈322行) | 同上 | | calculateHeightWidthRatio | 条件 endX === 0 时直接返回 0 | | calculateAngles | 在 Math.atan() 调用前检查 isNaN() / !isFinite(),若无效则回落至 minAngle / -minAngle 安全值 |

2. src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts

renderCurve() 方法开头增加防御层:遍历所有 8 个控制点,若任一坐标 isNaN() 则直接 return undefined,避免生成无效 SVG 元素。

验证结果

  • TypeScript 编译:通过
  • 全部 195 个单元测试:通过
  • Webpack 生产构建:成功