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 🙏

© 2024 – Pkg Stats / Ryan Hefner

vtubestudio

v3.10.1

Published

A TypeScript implementation of the VTube Studio WebSocket API.

Downloads

160

Readme

VTubeStudioJS

npm GitHub

An implementation of the WebSocket-based VTube Studio API for Node and browser JavaScript.

See the generated API documentation for type definitions and comments for the various public classes and interfaces, or use an editor with TypeScript support to automatically get types and comments when inspecting objects and fields.

See the official VTube Studio API documentation for more details on the semantic meaning of individual fields and the behaviors of the various API calls.

Install

# NPM
npm i vtubestudio
# Yarn
yarn add vtubestudio

This package has no runtime dependencies. To avoid node_modules bloat, use npm install --only=prod or NODE_ENV=production to skip unnecessary dev dependencies.

Usage

Basic Usage

This library is platform-agnostic, allowing it to be used for both Node projects and for browsers via tools like webpack. Use it by importing and instantiating an ApiClient:

// ES Modules (NodeJS or browser with bundler)
import { ApiClient } from "vtubestudio";

// CommonJS/Require (NodeJS)
const vts = require("vtubestudio");
const ApiClient = vts.ApiClient;

// ES Modules (CDN)
import { ApiClient } from "https://unpkg.com/vtubestudio/lib/esm/vtubestudio.min.js?module";

// Global Variable (CDN)
// <script src="https://unpkg.com/vtubestudio/lib/iife/vtubestudio.min.js">
const ApiClient = VTubeStudio.ApiClient;

function setAuthToken(authenticationToken) {
  // store the authentication token somewhere
}

function getAuthToken() {
  // retrieve the stored authentication token
}

const options = {
  authTokenGetter: getAuthToken,
  authTokenSetter: setAuthToken,
  pluginName: "Your Plugin Name",
  pluginDeveloper: "Your User Name",

  // Optionally set the URL or port to connect to VTube Studio at; defaults are as below:

  //port: 8001,
  //url: "ws://localhost:${port}",
};

const apiClient = new ApiClient(options);

See IApiClientOptions in the docs for all available options.

The ApiClient automatically handles connecting to the VTube Studio API, including seamlessly reconnecting broken WebSocket connections, and authenticating your plugin with VTube Studio. To enable these features, you must provide the authTokenGetter and authTokenSetter functions above, to persist the authentication token generated by VTube Studio.

Barebones implementations, for reference:

// Browser

function setAuthToken(authenticationToken) {
  localStorage.setItem("VTS_AUTH_TOKEN", authenticationToken);
}

function getAuthToken() {
  return localStorage.getItem("VTS_AUTH_TOKEN");
}

// NodeJS

function setAuthToken(authenticationToken) {
  fs.writeFileSync("./auth-token.txt", authenticationToken, {
    encoding: "utf-8",
  });
}

function getAuthToken() {
  return fs.readFileSync("./auth-token.txt", "utf-8");
}

Avoiding Timeout Errors

API calls may throw an error if the API client is not prepared to send requests; it may not be able to connect to VTube Studio, it may be waiting for the user to accept the authentication prompt, or the Plugin API might be disabled in VTube Studio settings. For best results, wrap every call in a try-catch, and use the following patterns where applicable:

// Run commands when the client connects:
apiClient.on("connect", async () => {
  // The API client just finished authenticating with VTube Studio, or reconnecting if it lost connection.

  // Run any commands you need to persist across reconnections here, such as event subscriptions:
  apiClient.events.modelLoaded.subscribe((data) => {
    // ...
  });
  // ...
});

// Check if the client is connected before running commands:
if (apiClient.isConnected) {
  const response = await apiClient.currentModel();
  // ...
}

Making API Calls

The API client exposes the request/response message pairs provided by the VTube Studio API as single asynchronous functions. You can use them like so:

// async/await
async function loadModel() {
  try {
    const response = await apiClient.modelLoad({ modelID: "YourNewModelID" });
    console.log("Successfully loaded model:", response.modelID);
  } catch (e) {
    console.error("Failed to load model:", e.errorID, e.message);
  }
}
// Promise callbacks
apiClient
  .modelLoad({ modelID: "YourNewModelID" })
  .then((response) => {
    console.log("Successfully loaded model:", response.modelID);
  })
  .catch((e) => {
    console.error("Failed to load model:", e.errorID, e.message);
  });

See ApiClient in the docs for all available calls, and review the official VTube Studio API documentation for more details on what calls are available and what each field means. In general, you pass an object representing the data property of the request to the library method, and get an object back representing the data property of the response. If the request data object is empty, the request method instead takes no parameters, and if the response data object is empty, the request method returns Promise<void>.

Subscribing to API Events

To subscribe to VTube Studio events, such as the ModelLoadedEvent, call the functions in apiClient.events, like this:

apiClient.events.modelLoaded.subscribe((data) => {
  // this callback will fire every time a model is loaded or unloaded in VTube Studio
  console.log("Model loaded:" + data.modelName);
});

Setting API Call Options

An additional options object may be passed as the second parameter to control the execution of the API call. For example, to change the default timeout to 1 minute:

const stats = await apiClient.statistics(undefined, { timeout: 1 * 60 * 1000 });

WebSockets

The API client expects a WebSocket implementation to be available. In the browser, the native WebSocket will be used automatically. In NodeJS or other contexts, you must provide an external implementation, such as the one from the ws package. In this case, you can explicitly provide a webSocketFactory function, like so:

const WebSocket = require("ws");

const options = {
  // ...
  webSocketFactory: (url) => new WebSocket(url),
};

const apiClient = new ApiClient(options);

Examples

Examples are included in the repository's examples folder for a React app (created with create-react-app) and a plain NodeJS app.

Breaking Changes in 3.2.0

Version v3.2.0 contains a minor breaking change from previous versions:

  • The ApiClient no longer attempts to import the ws package, due to complications with bundling for browser environments when the ws package is present in the package hierarchy. In NodeJS and other server environments, you must explicitly pass a WebSocket constructor via the webSocketFactory option. See the example above for reference.

Breaking Changes in 3.x.x

Version v3.x.x contains several breaking changes from previous versions:

  • The constructor for ApiClient was changed to take an options object, instead of the factory methods or a taking a message bus.
  • The message bus abstractions (WebSocketBus and related functions) have been removed.
  • The ApiClient automatically handles instantiating WebSockets, connecting to VTube Studio, and making authentication calls. These no longer need to be performed manually by plugin code.
  • The object-oriented wrapper classes (Plugin, CurrentModel, Expression, etc.) have been fully removed. The automatic authentication flow provided by Plugin has been rolled into ApiClient.
  • Error codes related to message bus failures (MessageBusError, and MessageBusClosed) have been removed, as WebSocket errors are now handled silently by ApiClient.
  • The typings provided for API call methods that take no data payload now explicitly call for undefined as the data object instead of void, which would accept anything.

Breaking Changes in 2.x.x

Version v2.x.x contains several breaking changes from previous versions:

  • The constructor for ApiClient was marked as private, and replaced with two factory methods: ApiClient.fromWebSocket(ws) and ApiClient.fromMessageBus(bus), to avoid unnecessarily exposing the end user to the library's message bus abstractions.
    • It is recommended that normal users should pass the websocket object to ApiClient.fromWebSocket(ws) directly instead of creating a WebSocketBus and passing that to new ApiClient(bus) or ApiClient.fromMessageBus(bus).
  • The object-oriented wrapper classes (Plugin, CurrentModel, Expression, etc.) have been deprecated, and will be removed in the next major version. The stateful nature of the wrappers implied that they were somehow synchronized with VTube Studio, but this was not the case. This became even more obvious with the introduction of highly dynamic concepts like Live2D items and expressions.
    • Users should switch to making calls to the API directly using the ApiClient class instead of the methods on Plugin. This unfortunately also includes handling the authentication workflow yourself for now. A basic example is provided above.
    • A future release may extend the ApiClient class to provide the automatic authentication handling that the Plugin class provided.
  • The MockApiServer class has been removed (as well as the related class EchoBus). This class was not intended to be used in production code and was a poor substitute for testing against VTube Studio itself.
  • Expression parameters were changed to use the new shape { name: string, value: number } instead of the deprecated { id: string, target: number }.
  • The ErrorCode enum values InternalClientError, MessageBusError, and MessageBusClosed were changed to -100, -101, and -102 to avoid conflicting with -1 (used in the VTube Studio API to indicate the absence of an error).
    • Code using the enum itself should continue to work as expected, but any code directly checking for the error code numbers will need to be manually fixed.

Contributing

Pull requests welcome! Please adhere to the linting and default formatting provided by the TypeScript compiler, and ensure that your code successfully compiles before opening your PR.

After cloning the repository or fetching the latest code:

npm install

Before opening a pull request, ensure your code compiles:

npm run build

License

MIT © 2022 Joshua Thome