youtube-automation/DIRECTUS_FLOW_SETUP.md

212 lines
6.0 KiB
Markdown

# Directus Flow Setup Guide - YouTube Thumbnail Automation
## Overview
This guide sets up a Directus Flow to automatically extract YouTube thumbnails when `media_items` are created or updated with `type` = `youtube_video` or `youtube`.
## Prerequisites
1. Access to your Directus admin at `https://enias.zeabur.app/admin`
2. Admin permissions to create flows and modify collections
## Step 1: Add youtube_thumbnail Field to media_items Collection
1. Go to **Settings****Data Model****media_items**
2. Click **Create Field**
3. Configure the field:
- **Field Name**: `youtube_thumbnail`
- **Type**: File
- **Interface**: File (Image)
- **Display Template**: Show thumbnail preview in layouts
- **Required**: No
- **Default**: null
## Step 2: Create the YouTube Automation Flow
### 2.1 Create New Flow
1. Go to **Settings****Flows**
2. Click **Create Flow**
3. Configure basic settings:
- **Name**: "YouTube Thumbnail Auto-Population"
- **Status**: Active
- **Icon**: smart_display (or video icon)
- **Color**: #FF0000 (YouTube red)
- **Description**: "Automatically extract and populate YouTube thumbnails"
### 2.2 Configure Trigger
1. Click **Add Trigger**
2. Select **Event Hook** trigger
3. Configure trigger:
- **Scope**: Items
- **Actions**: Update, Create
- **Collections**: media_items
### 2.3 Add Filter Condition
In the trigger configuration, add a filter condition:
```json
{
"$and": [
{
"$or": [
{ "type": { "_eq": "youtube_video" } },
{ "type": { "_eq": "youtube" } }
]
},
{
"url": { "_nnull": true }
}
]
}
```
### 2.4 Create Operations
#### Operation 1: Extract Video ID (Run Script)
1. Add **Run Script** operation
2. Name: "Extract YouTube Video ID"
3. Code:
```javascript
// Extract YouTube video ID from URL
function extractYouTubeId(url) {
if (!url) return null;
// Handle different YouTube URL formats
const patterns = [
/(?:youtube\.com\/watch\?v=)([a-zA-Z0-9_-]{11})/,
/(?:youtu\.be\/)([a-zA-Z0-9_-]{11})/,
/(?:youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/,
/(?:youtube\.com\/v\/)([a-zA-Z0-9_-]{11})/
];
for (const pattern of patterns) {
const match = url.match(pattern);
if (match) return match[1];
}
return null;
}
const videoId = extractYouTubeId($trigger.payload.url);
if (!videoId) {
throw new Error('Could not extract YouTube video ID from URL: ' + $trigger.payload.url);
}
// Generate thumbnail URLs with quality fallback
const thumbnailUrls = [
`https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`,
`https://img.youtube.com/vi/${videoId}/hqdefault.jpg`,
`https://img.youtube.com/vi/${videoId}/mqdefault.jpg`,
`https://img.youtube.com/vi/${videoId}/default.jpg`
];
module.exports = {
video_id: videoId,
thumbnail_urls: thumbnailUrls
};
```
#### Operation 2: Download & Upload Thumbnail (Run Script)
1. Add **Run Script** operation
2. Name: "Download and Upload Thumbnail"
3. Code:
```javascript
const axios = require('axios');
// Download thumbnail and upload to Directus
async function downloadAndUploadThumbnail(thumbnailUrls, videoId) {
// Try each thumbnail URL until we find one that works
for (const url of thumbnailUrls) {
try {
// Download thumbnail
const response = await axios.get(url, {
responseType: 'arraybuffer',
timeout: 10000,
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; DirectusBot/1.0)'
}
});
if (response.status === 200 && response.data.length > 1000) { // Ensure it's a valid image
// Upload to Directus files collection
const fileData = {
title: `YouTube Thumbnail - ${videoId}`,
filename_download: `youtube_${videoId}.jpg`,
type: 'image/jpeg',
storage: 'local',
data: Buffer.from(response.data).toString('base64')
};
const uploadResult = await $directus.files.createOne(fileData);
return uploadResult.id;
}
} catch (error) {
console.log(`Failed to download from ${url}:`, error.message);
continue; // Try next URL
}
}
throw new Error('Failed to download thumbnail from any source');
}
const fileId = await downloadAndUploadThumbnail(
$last.thumbnail_urls,
$last.video_id
);
module.exports = { thumbnail_file_id: fileId };
```
#### Operation 3: Update Media Item (Update Data)
1. Add **Update Data** operation
2. Configure:
- **Collection**: media_items
- **Key**: `{{$trigger.key}}`
- **Payload**:
```json
{
"youtube_thumbnail": "{{$last.thumbnail_file_id}}"
}
```
## Step 3: Test the Flow
### Test Data
Create or update a `media_items` record with:
- `type`: "youtube_video"
- `url`: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
### Expected Result
The Flow should automatically:
1. Extract video ID: `dQw4w9WgXcQ`
2. Download the best available thumbnail
3. Upload it to Directus files
4. Update the `youtube_thumbnail` field with the file reference
## Step 4: Verify Integration
1. Check **Activity** tab for flow execution logs
2. Verify `youtube_thumbnail` field is populated
3. Confirm thumbnail displays in collection layouts
4. Test with different YouTube URL formats
## Troubleshooting
### Common Issues
1. **Flow not triggering**: Check filter conditions and collection name
2. **Thumbnail download fails**: YouTube may block requests - add retry logic
3. **File upload fails**: Check Directus storage configuration
4. **Permission errors**: Ensure flow has file creation permissions
### Debug Tips
1. Enable flow logging in Settings
2. Check Activity logs for error details
3. Test operations individually
4. Verify field permissions and data types
## Alternative Approach: HTTP Request Operation
If the Run Script approach doesn't work, you can use HTTP Request operations:
1. **HTTP Request** to download thumbnail
2. **HTTP Request** to upload to Directus files API
3. **Update Data** to link the file
This approach uses the REST API instead of the JavaScript SDK.