← Back to Home

How to Schedule Video Publishing on YouTube

Updated January 14, 2026
youtubescheduled publishing15-minute slotstime calculation

Scheduling Video Publishing on YouTube

YouTube supports scheduled publishing with 15-minute time slot granularity.

15-Minute Time Slot Algorithm

Videos are scheduled to the next available 15-minute boundary (00, 15, 30, 45).

Rule: Always round UP to next slot (never current slot)

function calculateScheduledTime(baseTime?: Date): Date {
  const now = baseTime || new Date();
  const currentMinutes = now.getMinutes();
  const remainder = currentMinutes % 15;

  // If already on a 15-minute mark, go to the NEXT one
  const minutesToAdd = remainder === 0 ? 15 : 15 - remainder;

  const scheduledTime = new Date(now);
  scheduledTime.setMinutes(now.getMinutes() + minutesToAdd);
  scheduledTime.setSeconds(0);
  scheduledTime.setMilliseconds(0);

  return scheduledTime;
}

Examples

Current Time Scheduled Time
09:07 09:15
09:15 09:30
09:38 09:45
09:45 10:00
09:52 10:00
10:00 10:15

Staggered Batch Processing

Multiple videos are staggered by 15 minutes each:

function scheduleMultipleVideos(count: number, baseTime?: Date): Date[] {
  const scheduledTimes: Date[] = [];
  let currentTime = calculateScheduledTime(baseTime);

  for (let i = 0; i < count; i++) {
    scheduledTimes.push(new Date(currentTime));

    // Next video: 15 minutes later
    currentTime = new Date(currentTime.getTime() + 15 * 60 * 1000);
  }

  return scheduledTimes;
}

Example output for 3 videos at 09:38:

Video 1: 09:45
Video 2: 10:00
Video 3: 10:15

Upload with Scheduled Publishing

const scheduledTime = calculateScheduledTime();

const result = await youtubeClient.uploadVideo({
  videoPath: 'video.mp4',
  title: 'My Video',
  description: 'Video description',
  scheduledPublishTime: scheduledTime,  // Sets publishAt
});

Important Notes

Privacy Status

Scheduled videos must be private initially:

const status = {
  privacyStatus: scheduledPublishTime ? 'private' : 'private',
  publishAt: scheduledPublishTime?.toISOString(),  // ISO 8601 UTC
};

UTC Timestamps

YouTube API expects UTC timestamps:

const utcTime = scheduledTime.toISOString();  // "2026-01-14T00:45:00.000Z"

Timezone Display

For user display, convert to JST:

function formatJST(date: Date): string {
  return date.toLocaleString('ja-JP', {
    timeZone: 'Asia/Tokyo',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

// Example: "2026/01/14 09:45"

Compliance Audit Note

For projects created after July 28, 2020:

Complete Example

class SchedulingService {
  calculateScheduledTime(baseTime?: Date): Date {
    const now = baseTime || new Date();
    const currentMinutes = now.getMinutes();
    const remainder = currentMinutes % 15;
    const minutesToAdd = remainder === 0 ? 15 : 15 - remainder;

    const scheduledTime = new Date(now);
    scheduledTime.setMinutes(now.getMinutes() + minutesToAdd);
    scheduledTime.setSeconds(0);
    scheduledTime.setMilliseconds(0);

    return scheduledTime;
  }

  formatForDisplay(date: Date): string {
    return date.toLocaleString('ja-JP', {
      timeZone: 'Asia/Tokyo',
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
    });
  }

  // Usage
  const scheduled = this.calculateScheduledTime();
  console.log(`Scheduled: ${this.formatForDisplay(scheduled)} JST`);
  // Output: "Scheduled: 2026/01/14 09:45 JST"
}