> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/darkzOGx/youtube-automation-agent/llms.txt
> Use this file to discover all available pages before exploring further.

# PublishingSchedulingAgent

> AI-powered video publishing and scheduling agent

## Overview

The `PublishingSchedulingAgent` manages the complete video publishing workflow to YouTube. It handles scheduling, uploads, metadata optimization, thumbnail uploads, caption uploads, and publishing analytics.

## Constructor

<ParamField path="db" type="Database" required>
  Database instance for publish queue and analytics
</ParamField>

<ParamField path="credentials" type="Credentials" required>
  Credentials manager with YouTube API OAuth access
</ParamField>

```javascript theme={null}
const { PublishingSchedulingAgent } = require('./agents/publishing-scheduling-agent');

const agent = new PublishingSchedulingAgent(db, credentials);
```

## Properties

<ResponseField name="youtube" type="YouTubeAPI">
  YouTube Data API v3 client
</ResponseField>

<ResponseField name="publishQueue" type="Array">
  Queue of scheduled and published content
</ResponseField>

<ResponseField name="logger" type="Logger">
  Logger instance for tracking publishing operations
</ResponseField>

## Methods

### initialize()

Initializes the agent, sets up YouTube API, and loads publish queue.

<ParamField path="return" type="Promise<boolean>">
  Returns true when initialization is complete
</ParamField>

```javascript theme={null}
await agent.initialize();
// Sets up YouTube Data API v3 with OAuth credentials
// Loads existing publish queue from database
```

### scheduleContent(productionData)

Schedules content for future publishing.

<ParamField path="productionData" type="Object" required>
  Production data from ProductionManagementAgent
</ParamField>

<ParamField path="productionData.id" type="string" required>
  Production ID
</ParamField>

<ParamField path="productionData.script" type="Object" required>
  Video script with title
</ParamField>

<ParamField path="productionData.scheduledPublishTime" type="string" required>
  ISO timestamp for publishing
</ParamField>

<ParamField path="productionData.priority" type="number" required>
  Priority score
</ParamField>

<ParamField path="productionData.seo" type="Object" required>
  SEO metadata
</ParamField>

<ParamField path="productionData.assets" type="Object" required>
  All production assets
</ParamField>

<ParamField path="return" type="Promise<Object>">
  Schedule entry object
</ParamField>

```javascript theme={null}
const scheduleEntry = await agent.scheduleContent(productionData);

console.log(scheduleEntry);
// {
//   productionId: 'prod_123...',
//   title: 'JavaScript Tutorial',
//   publishTime: '2026-03-10T14:00:00.000Z',
//   status: 'scheduled',
//   priority: 75,
//   metadata: {
//     seo: { title: '...', description: '...', tags: [...] },
//     thumbnail: { path: '...' },
//     video: { path: '...' },
//     captions: { path: '...' }
//   },
//   createdAt: '2026-03-05T10:00:00.000Z'
// }
```

### publishContent(contentId)

Publishes content to YouTube immediately.

<ParamField path="contentId" type="string" required>
  Production ID or schedule entry ID
</ParamField>

<ParamField path="return" type="Promise<Object>">
  Updated schedule entry with YouTube ID and URL
</ParamField>

<ResponseField name="entry.status" type="string">
  Updated to 'published'
</ResponseField>

<ResponseField name="entry.publishedAt" type="string">
  ISO timestamp of actual publish time
</ResponseField>

<ResponseField name="entry.youtubeId" type="string">
  YouTube video ID
</ResponseField>

<ResponseField name="entry.youtubeUrl" type="string">
  Full YouTube video URL
</ResponseField>

```javascript theme={null}
const published = await agent.publishContent('prod_123...');

console.log('Published:', published.youtubeUrl);
// 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'

console.log('Video ID:', published.youtubeId);
// 'dQw4w9WgXcQ'
```

### uploadToYouTube(scheduleEntry)

Uploads video, thumbnail, and captions to YouTube.

<ParamField path="scheduleEntry" type="Object" required>
  Schedule entry with metadata and assets
</ParamField>

<ParamField path="return" type="Promise<Object>">
  YouTube API response with video ID
</ParamField>

```javascript theme={null}
const uploadResult = await agent.uploadToYouTube(scheduleEntry);
// Uploads:
// 1. Video file with metadata (title, description, tags, category)
// 2. Custom thumbnail
// 3. SRT captions
// Returns: { id: 'video_id', ... }
```

### uploadThumbnail(videoId, thumbnailPath)

Uploads custom thumbnail for a video.

<ParamField path="videoId" type="string" required>
  YouTube video ID
</ParamField>

<ParamField path="thumbnailPath" type="string" required>
  Path to thumbnail file
</ParamField>

<ParamField path="return" type="Promise<void>">
  Completes when upload succeeds
</ParamField>

```javascript theme={null}
await agent.uploadThumbnail('dQw4w9WgXcQ', '/path/to/thumbnail.jpg');
// Thumbnail must be:
// - 1280x720 resolution
// - Under 2MB
// - JPEG or PNG format
```

### uploadCaptions(videoId, captionsPath)

Uploads SRT captions for a video.

<ParamField path="videoId" type="string" required>
  YouTube video ID
</ParamField>

<ParamField path="captionsPath" type="string" required>
  Path to SRT caption file
</ParamField>

<ParamField path="return" type="Promise<void>">
  Completes when upload succeeds
</ParamField>

```javascript theme={null}
await agent.uploadCaptions('dQw4w9WgXcQ', '/path/to/captions.srt');
// Captions uploaded as English, not draft
```

### processPublishQueue()

Processes publish queue and auto-publishes ready content.

<ParamField path="return" type="Promise<number>">
  Number of videos published
</ParamField>

```javascript theme={null}
const published = await agent.processPublishQueue();
console.log('Auto-published', published, 'videos');

// Publishes all content where:
// - publishTime <= now
// - status === 'scheduled'
// Handles errors gracefully, marking failed items as 'failed'
```

### getUpcomingSchedule(days)

Gets upcoming scheduled publications.

<ParamField path="days" type="number" default="7">
  Number of days to look ahead
</ParamField>

<ParamField path="return" type="Promise<Array<Object>>">
  Array of upcoming schedule entries, sorted by publish time
</ParamField>

```javascript theme={null}
const upcoming = await agent.getUpcomingSchedule(7);

console.log('Upcoming publications:');
upcoming.forEach(entry => {
  console.log(`${entry.publishTime}: ${entry.title}`);
});
// 2026-03-10T14:00:00.000Z: JavaScript Tutorial
// 2026-03-12T14:00:00.000Z: Python Guide
// 2026-03-15T15:00:00.000Z: React Hooks Explained
```

### optimizePublishTimes()

Optimizes scheduled publish times based on channel analytics.

<ParamField path="return" type="Promise<void>">
  Completes when optimization is done
</ParamField>

```javascript theme={null}
await agent.optimizePublishTimes();
// Analyzes:
// - Channel statistics
// - Historical performance
// - Optimal days (Tuesday, Wednesday, Thursday)
// - Optimal hours (14:00, 15:00, 16:00, 20:00)
// Updates schedule entries with better times
```

### getChannelAnalytics()

Fetches channel analytics from YouTube.

<ParamField path="return" type="Promise<Object>">
  Channel analytics data
</ParamField>

<ResponseField name="analytics.totalViews" type="number">
  Total channel views
</ResponseField>

<ResponseField name="analytics.subscribers" type="number">
  Current subscriber count
</ResponseField>

<ResponseField name="analytics.videos" type="number">
  Total video count
</ResponseField>

<ResponseField name="analytics.optimalDays" type="Array<string>">
  Best days to publish
</ResponseField>

<ResponseField name="analytics.optimalHours" type="Array<number>">
  Best hours to publish
</ResponseField>

```javascript theme={null}
const analytics = await agent.getChannelAnalytics();
// {
//   totalViews: 150000,
//   subscribers: 5000,
//   videos: 50,
//   optimalDays: ['Tuesday', 'Wednesday', 'Thursday'],
//   optimalHours: [14, 15, 16, 20]
// }
```

### createPublishingReport()

Generates comprehensive publishing report.

<ParamField path="return" type="Promise<Object>">
  Publishing report with statistics and performance
</ParamField>

```javascript theme={null}
const report = await agent.createPublishingReport();

console.log(report);
// {
//   queueStatus: {
//     total: 10,
//     scheduled: 5,
//     published: 4,
//     failed: 1
//   },
//   upcomingPublications: [...],
//   recentPublications: [...],
//   performance: {
//     totalPublished: 4,
//     averageScheduleAccuracy: '98.5%',
//     averageDelay: '2.3 minutes',
//     publishingFrequency: '2.5 videos per week'
//   },
//   generatedAt: '2026-03-05T10:00:00.000Z'
// }
```

### emergencyPublish(contentId, delayMinutes)

Publishes content immediately or with short delay.

<ParamField path="contentId" type="string" required>
  Production ID
</ParamField>

<ParamField path="delayMinutes" type="number" default="0">
  Delay in minutes (0 for immediate)
</ParamField>

<ParamField path="return" type="Promise<Object>">
  Published or rescheduled entry
</ParamField>

```javascript theme={null}
// Publish immediately
const immediate = await agent.emergencyPublish('prod_123...', 0);

// Schedule 30 minutes from now
const delayed = await agent.emergencyPublish('prod_456...', 30);
```

### pauseScheduledContent(contentId)

Pauses scheduled content.

<ParamField path="contentId" type="string" required>
  Production ID
</ParamField>

<ParamField path="return" type="Promise<Object>">
  Updated entry with status 'paused'
</ParamField>

```javascript theme={null}
const paused = await agent.pauseScheduledContent('prod_123...');
console.log('Content paused:', paused.title);
```

### resumeScheduledContent(contentId, newPublishTime)

Resumes paused content.

<ParamField path="contentId" type="string" required>
  Production ID
</ParamField>

<ParamField path="newPublishTime" type="string" optional>
  New publish time (ISO string). If not provided, uses existing time.
</ParamField>

<ParamField path="return" type="Promise<Object>">
  Updated entry with status 'scheduled'
</ParamField>

```javascript theme={null}
// Resume with original time
const resumed = await agent.resumeScheduledContent('prod_123...');

// Resume with new time
const rescheduled = await agent.resumeScheduledContent(
  'prod_123...', 
  '2026-03-15T14:00:00.000Z'
);
```

## Upload Metadata Structure

YouTube video upload includes:

<CodeGroup>
  ```javascript Video Metadata theme={null}
  {
    snippet: {
      title: seo.title,
      description: seo.description,
      tags: seo.tags,
      categoryId: seo.metadata.category.toString(),
      defaultLanguage: 'en',
      defaultAudioLanguage: 'en'
    },
    status: {
      privacyStatus: 'public', // or 'private', 'unlisted'
      publishAt: scheduleEntry.publishTime,
      selfDeclaredMadeForKids: false
    }
  }
  ```

  ```javascript Thumbnail Upload theme={null}
  {
    videoId: videoId,
    media: {
      body: thumbnailBuffer  // 1280x720 JPEG/PNG under 2MB
    }
  }
  ```

  ```javascript Caption Upload theme={null}
  {
    snippet: {
      videoId: videoId,
      language: 'en',
      name: 'English Captions',
      isDraft: false
    },
    media: {
      body: captionsContent  // SRT formatted text
    }
  }
  ```
</CodeGroup>

## Usage Example

```javascript theme={null}
const { PublishingSchedulingAgent } = require('./agents/publishing-scheduling-agent');

const agent = new PublishingSchedulingAgent(db, credentials);
await agent.initialize();

// Schedule content from production
const productionData = await productionAgent.processContent(contentData);
const scheduled = await agent.scheduleContent(productionData);

console.log('Scheduled for:', scheduled.publishTime);

// View upcoming schedule
const upcoming = await agent.getUpcomingSchedule(14);
console.log('Next 14 days:', upcoming.length, 'videos');

// Auto-process queue (run this periodically)
const published = await agent.processPublishQueue();
console.log('Published:', published, 'videos');

// Generate report
const report = await agent.createPublishingReport();
console.log('Publishing accuracy:', report.performance.averageScheduleAccuracy);
console.log('Frequency:', report.performance.publishingFrequency);

// Optimize future publish times
await agent.optimizePublishTimes();
```

## Automated Publishing Workflow

<Accordion title="Schedule Content">
  Content is added to publish queue with calculated optimal publish time from strategy.
</Accordion>

<Accordion title="Queue Processing">
  Run processPublishQueue() on a cron job (e.g., every 5 minutes) to automatically publish content when time arrives.
</Accordion>

<Accordion title="Optimization">
  Periodically run optimizePublishTimes() (e.g., weekly) to adjust scheduled times based on analytics.
</Accordion>

<Accordion title="Monitoring">
  Use createPublishingReport() to track accuracy, frequency, and identify issues.
</Accordion>

## Best Practices

<Accordion title="Set Up Cron Jobs">
  Run processPublishQueue() every 5 minutes to ensure timely publishing. Most content publishes within 5 minutes of scheduled time.
</Accordion>

<Accordion title="Monitor Queue Status">
  Check for 'failed' status items and retry or investigate issues. Common failures: API rate limits, invalid video files, authentication errors.
</Accordion>

<Accordion title="Use Privacy Status Wisely">
  Default is 'public'. Use 'unlisted' for testing or 'private' for scheduled publishing with manual review.
</Accordion>

<Accordion title="Optimize Publish Times">
  Run optimizePublishTimes() weekly to adapt to audience behavior changes.
</Accordion>

<Accordion title="Emergency Publishing">
  Use emergencyPublish() for time-sensitive or trending topic videos that need immediate publication.
</Accordion>

## Environment Variables

<ParamField path="DEFAULT_PRIVACY_STATUS" type="string" default="public">
  Default privacy status for uploads: public, unlisted, or private
</ParamField>

## YouTube API Requirements

<Accordion title="OAuth 2.0 Credentials">
  Requires OAuth 2.0 credentials with YouTube Data API v3 scope: [https://www.googleapis.com/auth/youtube.upload](https://www.googleapis.com/auth/youtube.upload)
</Accordion>

<Accordion title="API Quotas">
  Video uploads cost 1600 quota units. Default quota is 10,000 units per day (6 uploads). Request quota increase for higher volume.
</Accordion>

<Accordion title="Rate Limits">
  YouTube enforces rate limits on uploads. The agent includes error handling for quota exceeded errors.
</Accordion>
