212 lines
6.0 KiB
Markdown
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. |