Spins
The Spins package in Wowza Flowplayer is a lightweight, TypeScript-based package designed to create short-form video experiences using Wowza Video playlists or inline arrays of video items. It provides a vertical video player component, optimized for formats like TikTok, Instagram Reels, and YouTube Shorts. This package automatically handles playlist loading and provides the structure needed for smooth, mobile-optimized video playback.
info
Spins is currently in beta. Features, APIs, and behaviors may change as development continues. We encourage testing in staging environments and welcome your feedback.
Before you start
Before you start working with the Spins package, we make the following assumptions and recommendations:
- You're familiar with the ECMAScript Module (ESM) approach of handling JavaScript modules.
- You have Node.js and Node Package Manager (npm) installed on your machine.
- Review the Token configuration section. To authorize the player, you need to configure it with your token.
- Ensure you have a Wowza Video subscription if you want to configure playlists in Wowza Video and use the playlist ID to configure the Spins package. For more, see get started with a Wowza Video trial .
Install Spins
The @flowplayer/spins package is available for download via npm (recommended), yarn, or as an ES (ECMAScript) module. It automatically includes all minimum player components and CSS to work with the Wowza Flowplayer.
// Install the spins package from npm
npm install @flowplayer/spins
// Import the package for use
import { createSpins, events } from "@flowplayer/spins";
yarn add @flowplayer/spins
<script type="module">
import {createSpins, events} from "https://player.wowza.com/spins/stable/index.js"
</script>
Configure Spins
To use the Spins package, configure it with the createSpins()
method. There are two ways to provide video content to Spins:
- Using a Wowza Video playlist ID – Use the playlist ID of an existing playlist from your Wowza Video account, and Spins will automatically load and display the content. For more information on how to create a playlist and get a playlist ID, see Overview of playlists and Playlist details page in Wowza Video .
-
Using an array of
SpinItem
objects – Use this method to manually define each video clip, including source URL, title, poster image, description, and plugins.
Property | Description |
---|---|
playlist string | SpinItem[] |
Defines a Wowza Video playlist ID (composite media ID) or an array of SpinItem objects. |
lang string Optional |
Sets the language of the player UI and messages. For example, en for English. |
token string Optional |
Adds a Wowza Flowplayer token required to license and use the player. |
ui Optional |
Sets UI configuration for customizing player appearance and behavior. |
ima Optional |
Configures the Ads plugin for use with the spins container. For configuration details, see the Ads plugin. |
share Optional |
Configures the Share plugin for use with the spins container. For configuration details, see the Share plugin. |
consent Optional |
Configures the Consent plugin for use with the spins container. For configuration details, see the Consent plugin. |
plugins Optional |
Sets plugins to include with the player. For example:["subtitles", "vtsel", "ads", "share", "thumbnails", "asel"] . |
SpinItem properties
Each SpinItem
represents a single short-form video and includes properties such as the video URL, title, poster image, and subtitles.
Property | Description |
---|---|
url string |
Defines the video source URL or media ID from Wowza Video for the video. |
title string Optional |
Defines a title for the video. |
poster string Optional |
Sets a poster image shown before the video plays. |
description string Optional |
Defines a short description of the video content. |
subtitles Optional |
Adds subtitles to the video. |
Example
The following examples use the properties from the previous table to import the Spins package from npm and to configure it with a Wowza Video playlist ID or with an array of customized spin items. You can also see how event listeners are used to manage the spins container.
import { createSpins, events } from "@flowplayer/spins";
// Use a playlist ID from Wowza Video
const playlistID = "c30850bc-eeeb-421d-9ed3-158339d0851a";
// Create Spins using playlist ID
const container = createSpins({
token: "[your-player-token]",
playlist: playlistID,
plugins: ["subtitles"]
});
// Listen for the SPIN_IN_VIEWPORT event
container.on(events.SPIN_IN_VIEWPORT, (ev) => {
const { config, spin, index } = ev.detail;
console.log("spin_in_viewport_data: ", config, spin, index);
// Add your code here
});
// Append the container to the DOM
document.body.append(container);
import { createSpins, events } from "@flowplayer/spins";
// Manually define an array of spin items
const spinItemArray = [
{
// Add media ID for a Wowza Video asset
url: "38a31588-07a0-49bf-ba55-fa0310e13f15"
},
{
url: "https://cf23f0bd0.lwcdn.com/hls/9eda7730-23e9-4462-9ad4-c53e8004c3e9/playlist.m3u8",
title: "A title",
description: "A description",
poster: "//cf23f0bd0.lwcdn.com/i/v-i-9eda7730-23e9-4462-9ad4-c53e8004c3e9-1.jpg"
},
{
url: "https://stdlwcdn.lwcdn.com/hls/2cd21de6-1586-428b-bf7f-acc3fdcfd697/playlist.m3u8",
poster: "//stdlwcdn.lwcdn.com/i/v-i-67059b8d-ce1a-457e-9af1-d927ff945826-1.jpg",
title: "Test - missing mp4 01/09/2025 14:57"
},
{
url: "https://cdn.flowplayer.com/d9cd469f-14fc-4b7b-a7f6-ccbfa755dcb8/hls/383f752a-cbd1-4691-a73f-a4e583391b3d/playlist.m3u8?t=1",
subtitles: {
tracks: [
{
src: "https://builds.flowplayer.com/samples/en.vtt",
lang: "en",
label: "English"
},
{
src: "https://builds.flowplayer.com/samples/pt.vtt",
lang: "pt",
label: "Portuguese"
}
]
}
}
];
// Create Spins using spin item array
const container = createSpins({
playlist: spinItemArray,
plugins: ["subtitles"]
});
// Listen for the SPIN_IN_VIEWPORT event
container.on(events.SPIN_IN_VIEWPORT, (ev) => {
const { config, spin, index } = ev.detail;
console.log("spin_in_viewport_data: ", config, spin, index);
// Add your code here
});
// Append the container to the DOM
document.body.append(container);
Listen to events
This section describes the events you can capture to control and manage your spins container.
Event | Description |
---|---|
SPIN_CREATED |
Emitted when a new spin is created |
SPIN_IN_VIEWPORT |
Emitted when a spin becomes visible in the view |
SpinsContainer methods
Method | Description |
---|---|
on(event: string, handler: (ev: CustomEvent) => void) |
Subscribes to an event (e.g., SPIN_CREATED , SPIN_IN_VIEWPORT ). |
off(event: string, handler: (ev: CustomEvent) => void) |
Removes a previously added event listener. |
addSpins(spinItems: SpinItem[]) |
Adds new spins to the container dynamically. Accepts an array of SpinItem objects. |
Example
This code initializes a Spins player instance using the createSpins
function with a specified playlist ID, access token, and language. It also sets up two event listeners:
spins.on(events.SPIN_CREATED, (ev) => {
const {config, spin, index} = ev.detail;
console.log("New spin created:", spin);
});
spins.on(events.SPIN_IN_VIEWPORT, (ev) => {
const {config, spin, index} = ev.detail;
console.log("Spin is now in viewport:", spin);
});
Control CSS styles
The package includes default CSS styling optimized for short-form content. You can override or extend these styles using standard CSS or CSS modules.
.fp-spins-container {
max-height: 100vh;
overflow: hidden;
background: #000;
}
flowplayer-spin {
border-radius: 10px;
}
Advanced usage
Configure with React
Spins also works seamlessly with React. Here's how you can embed it inside a React component:
import { createSpins } from "@flowplayer/spins";
import { useEffect, useRef } from "react";
function SpinsPlayer({ playlistId }: { playlistId: string }) {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!containerRef.current) return;
const spinsContainer = createSpins({
playlist: playlistId,
token: "[your-player-token]",
lang: "en"
});
containerRef.current.appendChild(spinsContainer);
return () => {
if (containerRef.current.contains(spinsContainer)) {
containerRef.current.removeChild(spinsContainer);
}
};
}, [playlistId]);
return <div ref={containerRef} className="spins-container" />;
}