
Security News
upm Launches as a Fast, Tiny Package Manager Written in TypeScript
upm uses Node.js to deliver fast npm installs in about 250 KB, with a JavaScript API and security defaults.
@xiboplayer/schedule
Advanced tools
Complete scheduling solution: campaigns, dayparting, interrupts, and overlays
Complete scheduling solution: campaigns, dayparting, interrupts, overlays, and timeline prediction.
Manages all aspects of digital signage scheduling to determine which layouts play when:
maxPlaysPerHour with even distribution (prevents bursts, ensures spacing)CMS Schedule XML
|
v
+-------------------------------------+
| Schedule Parser |
| +- campaigns[] |
| +- layouts[] |
| +- overlays[] |
| +- default layout |
+-------------------------------------+
|
v
+-------------------------------------+
| Evaluation Engine |
| +- Recurrence (Week/Day/Month) |
| +- Time windows (dayparting) |
| +- Criteria (weather, properties) |
| +- Geo-fencing |
| +- Priority + rate-limit filtering |
+-------------------------------------+
|
v
+-------------------------------------+
| Schedule Queue Builder (LCM-based) |
| Deterministic round-robin with: |
| +- Rate-limited slots (even spaced)|
| +- Priority fallback |
| +- Default fills gaps |
+-------------------------------------+
|
+-> getCurrentLayouts() -> Renderer
+-> getLayoutsInTimeRange() -> Timeline Overlay
+-> Track play history -> Rate limiting
npm install @xiboplayer/schedule
import { ScheduleManager } from '@xiboplayer/schedule';
const schedule = new ScheduleManager();
schedule.setSchedule({
campaigns: [
{
id: 1,
priority: 100,
fromdt: '2025-01-01 09:00',
todt: '2025-12-31 17:00',
recurrenceType: 'Week',
recurrenceRepeatsOn: '1,2,3,4,5', // Mon-Fri
layouts: [
{ id: 10, file: '10.xlf', duration: 30 },
{ id: 11, file: '11.xlf', duration: 30 },
],
},
],
default: '99.xlf',
});
const layoutsToPlay = schedule.getCurrentLayouts();
// Business hours: ['10.xlf', '11.xlf']
// After hours: ['99.xlf'] (default)
schedule.setSchedule({
layouts: [
{
id: 1,
file: '1.xlf',
recurrenceType: 'Week',
recurrenceRepeatsOn: '1,2,3,4,5,6,7',
fromdt: '1970-01-01 22:00:00', // 10 PM
todt: '1970-01-01 02:00:00', // 2 AM (next day)
},
],
});
// Friday 23:00: returns ['1.xlf']
// Saturday 01:00: returns ['1.xlf'] (midnight crossing works)
schedule.setSchedule({
layouts: [
{
id: 1,
file: '1.xlf',
maxPlaysPerHour: 3, // 3 times per hour, evenly spaced
},
],
});
schedule.recordPlay('1'); // Play at 09:00
// Can't play again until 09:20 (60 / 3 = 20 min minimum gap)
schedule.setSchedule({
layouts: [
{ id: 1, file: '1.xlf', duration: 30 },
{ id: 2, file: '2.xlf', duration: 30, shareOfVoice: 20 }, // 20% of each hour
],
});
const layouts = schedule.getCurrentLayouts();
// Interleaved: normal, normal, interrupt, normal, normal, interrupt, ...
schedule.setSchedule({
layouts: [
{
id: 1,
file: '1.xlf',
criteria: [
{ metric: 'weatherTemp', condition: 'greaterThan', value: '25', type: 'number' },
],
},
],
});
schedule.setWeatherData({ temperature: 28, humidity: 65 });
// Layout 1 displays only when temperature > 25
schedule.setLocation(37.7749, -122.4194);
schedule.setSchedule({
layouts: [
{
id: 1,
file: '1.xlf',
isGeoAware: true,
geoLocation: '37.7749,-122.4194,500', // lat,lng,radius_meters
},
],
});
// Returns ['1.xlf'] only if player is within 500m
const timeline = calculateTimeline(queue, queuePosition, {
from: new Date(),
hours: 2,
defaultLayout: schedule.schedule.default,
durations: durations,
});
// Returns:
// [
// { layoutFile: '10.xlf', startTime, endTime, duration: 30, isDefault: false },
// { layoutFile: '11.xlf', startTime, endTime, duration: 30, isDefault: false },
// ...
// ]
When getCurrentLayouts() is called:
maxPlaysPerHourThe queue is a pre-computed, deterministic round-robin cycle:
maxPlaysPerHour intervals (capped at 2 hours)| Type | Pattern | Example |
|---|---|---|
| Week | Specific days + time-of-day | Mon-Fri 09:00-17:00 |
| Day | Daily with optional interval | Every 2 days |
| Month | Specific days of month | 1st, 15th (monthly) |
Midnight crossing: 22:00 - 02:00 works across day boundaries.
Built-in metrics: dayOfWeek, dayOfMonth, month, hour, isoDay
Weather metrics: weatherTemp, weatherHumidity, weatherWindSpeed, weatherCondition, weatherCloudCover
Operators: equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals, contains, startsWith, endsWith, in
"lat,lng,radius" (e.g., "37.7749,-122.4194,500")new ScheduleManager(options?)
| Option | Type | Description |
|---|---|---|
interruptScheduler | InterruptScheduler? | Optional interrupt handler |
displayProperties | Object? | Custom display fields from CMS |
| Method | Returns | Description |
|---|---|---|
setSchedule(schedule) | void | Load schedule from XMDS response |
getCurrentLayouts() | string[] | Layouts active now |
getLayoutsAtTime(date) | string[] | Layouts at specific time |
getAllLayoutsAtTime(date) | Array | All time-active layouts with metadata |
getScheduleQueue(durations) | {queue, periodSeconds} | Pre-computed round-robin queue |
popNextFromQueue(durations) | {layoutId, duration} | Pop next entry, advance position |
peekNextInQueue(durations) | {layoutId, duration} | Peek without advancing |
recordPlay(layoutId) | void | Track a play for rate limiting |
canPlayLayout(layoutId, max) | boolean | Check if layout can play now |
setWeatherData(data) | void | Update weather for criteria |
setLocation(lat, lng) | void | Set GPS location for geo-fencing |
setDisplayProperties(props) | void | Set custom display fields |
detectConflicts(options) | Array | Find priority-shadowing conflicts |
| Method | Returns | Description |
|---|---|---|
setOverlays(overlays) | void | Update overlay list |
getCurrentOverlays() | Array | Active overlays (sorted by priority) |
shouldCheckOverlays(lastCheck) | boolean | Check interval (every 60s) |
import { calculateTimeline, parseLayoutDuration, buildScheduleQueue } from '@xiboplayer/schedule';
const { duration } = parseLayoutDuration(xlfXml, videoDurations?);
const { queue, periodSeconds } = buildScheduleQueue(allLayouts, durations);
const timeline = calculateTimeline(queue, position, { from, hours, defaultLayout, durations });
No external dependencies -- fully self-contained scheduling engine.
@xiboplayer/utils -- logging onlyxiboplayer.org · Part of the XiboPlayer SDK
FAQs
Complete scheduling solution: campaigns, dayparting, interrupts, and overlays
The npm package @xiboplayer/schedule receives a total of 26 weekly downloads. As such, @xiboplayer/schedule popularity was classified as not popular.
We found that @xiboplayer/schedule demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
upm uses Node.js to deliver fast npm installs in about 250 KB, with a JavaScript API and security defaults.

Company News
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.