6. Thumbnail and Video Streaming fix

This commit is contained in:
Manish Tanwar 2026-02-06 00:44:50 +05:30
parent 204cda6e75
commit ce92aee238
7 changed files with 82 additions and 39 deletions

View file

@ -28,7 +28,8 @@
"Bash(bash:*)",
"Bash(dos2unix:*)",
"WebSearch",
"WebFetch(domain:ai.google.dev)"
"WebFetch(domain:ai.google.dev)",
"Bash(xargs:*)"
]
}
}

View file

@ -68,10 +68,11 @@ Create the following directories on your server:
```
/var/www/html/lux-studio/
├── api/ # Create this directory
├── generated_videos/ # Create this directory
├── generated_images/ # Create this directory
└── uploads/ # Create this directory
├── api/ # PHP files go here
├── generated_videos/ # Video output (writable)
├── generated_images/ # Image output (writable)
└── uploads/ # Session uploads (writable)
└── sessions/ # Auto-created per user session
```
**Commands to create directories:**
@ -79,9 +80,11 @@ Create the following directories on your server:
sudo mkdir -p /var/www/html/lux-studio/api
sudo mkdir -p /var/www/html/lux-studio/generated_videos
sudo mkdir -p /var/www/html/lux-studio/generated_images
sudo mkdir -p /var/www/html/lux-studio/uploads
sudo mkdir -p /var/www/html/lux-studio/uploads/sessions
```
**Important**: PHP files use `dirname(__DIR__)` to store uploads/videos at `/var/www/html/lux-studio/` (NOT inside `/api/`). This keeps generated content separate from code.
---
## Step 3: Files to Upload
@ -208,6 +211,9 @@ sudo chmod -R 755 assets/
sudo chmod -R 755 api/
# Writable directories for generated content
sudo chown -R www-data:www-data generated_videos/
sudo chown -R www-data:www-data generated_images/
sudo chown -R www-data:www-data uploads/
sudo chmod -R 775 generated_videos/
sudo chmod -R 775 generated_images/
sudo chmod -R 775 uploads/
@ -216,17 +222,31 @@ sudo chmod -R 775 uploads/
sudo chmod 640 api/config.php
```
**Note**: The `uploads/sessions/` subdirectories are created automatically by PHP when users start sessions.
---
## Step 6: Enable Apache Rewrite Module
## Step 6: Apache Configuration
### 6.1 Check if mod_rewrite is enabled
```bash
apache2ctl -M | grep rewrite
```
If not enabled:
```bash
sudo a2enmod rewrite
sudo systemctl restart apache2
```
Ensure your Apache virtual host has `AllowOverride All`:
### 6.2 Enable AllowOverride for lux-studio
Edit your Apache site config:
```bash
sudo nano /etc/apache2/sites-enabled/000-default.conf
```
Add inside the `<VirtualHost>` block:
```apache
<Directory /var/www/html/lux-studio>
AllowOverride All
@ -238,6 +258,8 @@ Then restart Apache:
sudo systemctl restart apache2
```
**Note**: This only affects the `/lux-studio/` directory and won't impact other apps on the server.
---
## Complete Directory Structure After Deployment
@ -261,11 +283,18 @@ sudo systemctl restart apache2
│ ├── webhook_logger.php # Webhook logging
│ ├── env_loader.php # Environment loading
│ └── config.php # Created on server
├── generated_videos/ # Empty, writable
├── generated_images/ # Empty, writable
└── uploads/ # Empty, writable
├── generated_videos/ # Video output (writable, www-data owned)
├── generated_images/ # Image output (writable, www-data owned)
└── uploads/ # Session data (writable, www-data owned)
└── sessions/ # Auto-created per-user session directories
└── {session_id}/ # Created automatically
└── images/ # User uploaded/generated images
```
**Storage Paths** (configured in PHP files using `dirname(__DIR__)`):
- Images: `/var/www/html/lux-studio/uploads/sessions/{session_id}/images/`
- Videos: `/var/www/html/lux-studio/generated_videos/`
---
## Azure AD Configuration
@ -308,12 +337,14 @@ You have **two separate Azure AD App Registrations**:
| Issue | Solution |
|-------|----------|
| 404 on assets | Verify all files from `dist/` are uploaded, check `base` path in vite.config.js |
| 404 on logo | Ensure `LUX_STUDIO_LOGO.svg` exists at `/var/www/html/lux-studio/LUX_STUDIO_LOGO.svg` |
| SSO login fails | Verify redirect URI in Azure Portal matches exactly: `https://ai-sandbox.oliver.solutions/lux-studio/` |
| SSO uses wrong Client ID | Ensure you built with `npm run build` (uses `.env.production`), not `npm run dev` |
| SSO redirect loop | Clear browser localStorage, check Azure AD redirect URI configuration |
| API 500 errors | Check PHP logs: `sudo tail -f /var/log/apache2/error.log` |
| .htaccess not working | Ensure `mod_rewrite` is enabled and `AllowOverride All` is set |
| Generation fails | Check directories exist and are writable by Apache user |
| .htaccess not working | Ensure `mod_rewrite` is enabled and `AllowOverride All` is set for lux-studio directory |
| Failed to save image | Create `uploads/sessions` directory and set ownership: `sudo mkdir -p /var/www/html/lux-studio/uploads/sessions && sudo chown -R www-data:www-data /var/www/html/lux-studio/uploads` |
| Generation fails | Check directories exist and are writable by Apache user (www-data) |
### SSO Debug Tips

View file

@ -28,6 +28,16 @@ class VeoVideoAPI {
private $baseUrl = 'https://generativelanguage.googleapis.com/v1beta/models';
private $model;
/**
* Get API base path for URLs (production-aware)
*/
private function getApiBasePath() {
// Check if we're in production (lux-studio subdirectory)
return (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '/lux-studio/') !== false)
? '/lux-studio/api'
: '/api';
}
// Available models
private static $models = [
'standard' => 'veo-3.1-generate-preview',
@ -449,7 +459,7 @@ try {
'video' => [
'filename' => $filename,
'mime_type' => $videoData['mime_type'],
'url' => '/api/stream_video.php?file=' . urlencode($filename)
'url' => $this->getApiBasePath() . '/stream_video.php?file=' . urlencode($filename)
]
]);
} else if ($videoData['type'] === 'uri') {
@ -491,7 +501,7 @@ try {
'video' => [
'filename' => $filename,
'mime_type' => $videoData['mime_type'],
'url' => '/api/stream_video.php?file=' . urlencode($filename)
'url' => $this->getApiBasePath() . '/stream_video.php?file=' . urlencode($filename)
]
]);
} else {
@ -571,7 +581,7 @@ try {
echo json_encode([
'success' => true,
'video' => [
'url' => '/api/stream_video.php?file=' . urlencode($filename),
'url' => $this->getApiBasePath() . '/stream_video.php?file=' . urlencode($filename),
'filename' => $filename,
'mime_type' => 'video/mp4'
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/lux-studio/LUX_STUDIO_LOGO.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lux Studio - AI Cinematography</title>
<script type="module" crossorigin src="/lux-studio/assets/index-CQhyuIyu.js"></script>
<script type="module" crossorigin src="/lux-studio/assets/index-5_WjmgQu.js"></script>
<link rel="stylesheet" crossorigin href="/lux-studio/assets/index-S7O61I6c.css">
</head>
<body class="bg-slate-950">

View file

@ -1,5 +1,6 @@
import React, { useRef, useState, useEffect } from 'react';
import { Play, Pause, SkipBack, SkipForward, Volume2, VolumeX, Download, Image, Scissors, ChevronLeft, ChevronRight, FolderPlus, Check } from 'lucide-react';
import { getApiUrl } from '../utils/api';
/**
* VideoPlayer component with frame extraction capability
@ -15,7 +16,7 @@ const VideoPlayer = ({ src, onFrameExtract, onSaveToProject, className = '', aut
// Convert old /generated_videos/ URLs to streaming endpoint for seeking support
const videoSrc = src?.startsWith('/generated_videos/')
? `/api/stream_video.php?file=${encodeURIComponent(src.replace('/generated_videos/', ''))}`
? `${getApiUrl('stream_video.php')}?file=${encodeURIComponent(src.replace('/generated_videos/', ''))}`
: src;
const [isPlaying, setIsPlaying] = useState(false);