cleanup and fixes
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m15s

This commit is contained in:
2026-02-09 18:50:06 -05:00
parent 2c2bf21c37
commit eab55d2e01
2 changed files with 140 additions and 36 deletions

14
app.py
View File

@@ -114,6 +114,15 @@ def process_video():
# Build filter complex for crop and scale # Build filter complex for crop and scale
filters = [] filters = []
# Add rotation filter if specified
rotation = data.get('rotation', 0)
if rotation == 90:
filters.append('transpose=1')
elif rotation == 180:
filters.append('transpose=2,transpose=2')
elif rotation == 270:
filters.append('transpose=2')
# Add crop filter if specified # Add crop filter if specified
crop = data.get('crop') crop = data.get('crop')
if crop: if crop:
@@ -136,6 +145,11 @@ def process_video():
if filters: if filters:
cmd.extend(['-vf', ','.join(filters)]) cmd.extend(['-vf', ','.join(filters)])
# Handle audio
mute_audio = data.get('mute_audio', False)
if mute_audio:
cmd.extend(['-an']) # Remove audio
# Output settings for H.264 MP4 # Output settings for H.264 MP4
cmd.extend([ cmd.extend([
'-c:v', 'libx264', '-c:v', 'libx264',

View File

@@ -123,8 +123,14 @@
} }
.video-preview { .video-preview {
margin: 20px 0; margin: 20px auto;
text-align: center; text-align: center;
position: relative;
display: flex;
justify-content: center;
}
.video-wrapper {
position: relative; position: relative;
display: inline-block; display: inline-block;
} }
@@ -217,6 +223,41 @@
transform: translateY(0); transform: translateY(0);
} }
.quick-actions {
display: flex;
gap: 10px;
margin: 15px 0;
flex-wrap: wrap;
}
.quick-action-btn {
flex: 1;
min-width: 150px;
padding: 10px 16px;
background: white;
color: #667eea;
border: 2px solid #667eea;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.quick-action-btn:hover {
background: #667eea;
color: white;
transform: translateY(-1px);
}
.quick-action-btn.active {
background: #667eea;
color: white;
}
.current-time-display { .current-time-display {
background: white; background: white;
padding: 10px 15px; padding: 10px 15px;
@@ -462,16 +503,57 @@
<h2>2. Edit Video</h2> <h2>2. Edit Video</h2>
<div class="video-preview"> <div class="video-preview">
<div class="video-wrapper">
<video id="video-preview" controls></video> <video id="video-preview" controls></video>
<canvas id="crop-canvas" class="crop-canvas"></canvas> <canvas id="crop-canvas" class="crop-canvas"></canvas>
</div> </div>
</div>
<div class="video-info" id="video-info"></div>
<!-- Quick Actions -->
<div class="form-group">
<label>⚡ Quick Actions</label>
<div class="quick-actions">
<button class="quick-action-btn" id="mute-audio-btn" title="Remove audio track from video">
🔇 Mute Audio
</button>
<button class="quick-action-btn" id="rotate-btn" title="Rotate video 90° clockwise">
🔄 Rotate 90°
</button>
</div>
</div>
<!-- Crop Controls -->
<div class="form-group">
<label>✂️ Crop Video</label>
<div class="video-controls"> <div class="video-controls">
<button class="crop-mode-btn" id="crop-mode-btn">🎯 Click to Draw Crop Area</button> <button class="crop-mode-btn" id="crop-mode-btn">🎯 Click to Draw Crop Area</button>
<p class="crop-hint" id="crop-hint" style="display: none;">Click and drag on the video to select crop area</p> <p class="crop-hint" id="crop-hint" style="display: none;">Click and drag on the video to select crop area</p>
</div> </div>
<div class="crop-controls">
<div class="video-info" id="video-info"></div> <div class="form-row">
<div>
<label style="font-weight: normal;">X Position</label>
<input type="number" id="crop-x" value="0" min="0">
</div>
<div>
<label style="font-weight: normal;">Y Position</label>
<input type="number" id="crop-y" value="0" min="0">
</div>
</div>
<div class="form-row" style="margin-top: 10px;">
<div>
<label style="font-weight: normal;">Crop Width</label>
<input type="number" id="crop-width" placeholder="Full width" min="0">
</div>
<div>
<label style="font-weight: normal;">Crop Height</label>
<input type="number" id="crop-height" placeholder="Full height" min="0">
</div>
</div>
</div>
</div>
<!-- Trim Controls --> <!-- Trim Controls -->
<div class="form-group"> <div class="form-group">
@@ -523,33 +605,6 @@
</div> </div>
</div> </div>
<!-- Crop Controls -->
<div class="form-group">
<label>✂️ Crop Video (optional)</label>
<div class="crop-controls">
<div class="form-row">
<div>
<label style="font-weight: normal;">X Position</label>
<input type="number" id="crop-x" value="0" min="0">
</div>
<div>
<label style="font-weight: normal;">Y Position</label>
<input type="number" id="crop-y" value="0" min="0">
</div>
</div>
<div class="form-row" style="margin-top: 10px;">
<div>
<label style="font-weight: normal;">Crop Width</label>
<input type="number" id="crop-width" placeholder="Full width" min="0">
</div>
<div>
<label style="font-weight: normal;">Crop Height</label>
<input type="number" id="crop-height" placeholder="Full height" min="0">
</div>
</div>
</div>
</div>
<div class="button-group"> <div class="button-group">
<button class="btn" id="process-btn">🎬 Process Video</button> <button class="btn" id="process-btn">🎬 Process Video</button>
<button class="btn btn-secondary" id="reset-btn">🔄 Start Over</button> <button class="btn btn-secondary" id="reset-btn">🔄 Start Over</button>
@@ -579,6 +634,8 @@
let cropStartY = 0; let cropStartY = 0;
let cropRect = null; let cropRect = null;
let scalePercentage = 100; let scalePercentage = 100;
let rotationDegrees = 0;
let muteAudio = false;
// Upload area handling // Upload area handling
const uploadArea = document.getElementById('upload-area'); const uploadArea = document.getElementById('upload-area');
@@ -808,6 +865,29 @@
currentTimeDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds}`; currentTimeDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds}`;
}); });
// Quick actions
document.getElementById('mute-audio-btn').addEventListener('click', function() {
muteAudio = !muteAudio;
if (muteAudio) {
this.classList.add('active');
this.textContent = '🔇 Audio Muted';
} else {
this.classList.remove('active');
this.textContent = '🔇 Mute Audio';
}
});
document.getElementById('rotate-btn').addEventListener('click', function() {
rotationDegrees = (rotationDegrees + 90) % 360;
if (rotationDegrees === 0) {
this.classList.remove('active');
this.textContent = '🔄 Rotate 90°';
} else {
this.classList.add('active');
this.textContent = `🔄 Rotated ${rotationDegrees}°`;
}
});
// Set start time button // Set start time button
setStartBtn.addEventListener('click', () => { setStartBtn.addEventListener('click', () => {
const currentTime = videoPreview.currentTime; const currentTime = videoPreview.currentTime;
@@ -883,7 +963,9 @@
file_id: currentFileId, file_id: currentFileId,
start_time: startTime, start_time: startTime,
end_time: endTime, end_time: endTime,
scale_percentage: scalePercentage scale_percentage: scalePercentage,
rotation: rotationDegrees,
mute_audio: muteAudio
}; };
if (cropWidth > 0 && cropHeight > 0) { if (cropWidth > 0 && cropHeight > 0) {
@@ -944,6 +1026,8 @@
videoInfo = null; videoInfo = null;
cropMode = false; cropMode = false;
cropRect = null; cropRect = null;
rotationDegrees = 0;
muteAudio = false;
videoPreview.src = ''; videoPreview.src = '';
videoInput.value = ''; videoInput.value = '';
@@ -953,6 +1037,12 @@
cropModeBtn.textContent = '🎯 Click to Draw Crop Area'; cropModeBtn.textContent = '🎯 Click to Draw Crop Area';
cropHint.style.display = 'none'; cropHint.style.display = 'none';
// Reset quick actions
document.getElementById('mute-audio-btn').classList.remove('active');
document.getElementById('mute-audio-btn').textContent = '🔇 Mute Audio';
document.getElementById('rotate-btn').classList.remove('active');
document.getElementById('rotate-btn').textContent = '🔄 Rotate 90°';
document.getElementById('upload-section').classList.remove('hidden'); document.getElementById('upload-section').classList.remove('hidden');
document.getElementById('edit-section').classList.add('hidden'); document.getElementById('edit-section').classList.add('hidden');
document.getElementById('download-section').classList.add('hidden'); document.getElementById('download-section').classList.add('hidden');