please merge

This commit is contained in:
2025-07-26 16:02:07 -07:00
parent 366b132ef5
commit 4958c503dd

View File

@@ -398,39 +398,35 @@ class VideoProcessor:
overlap_frames: Number of overlapping frames overlap_frames: Number of overlapping frames
audio_source: Audio source file for final video audio_source: Audio source file for final video
""" """
from .streaming_video_writer import StreamingVideoWriter
if not chunk_files: if not chunk_files:
raise ValueError("No chunk files to merge") raise ValueError("No chunk files to merge")
print(f"🎬 Streaming merge: {len(chunk_files)} chunks → {output_path}") print(f"🎬 Streaming merge: {len(chunk_files)} chunks → {output_path}")
# Initialize streaming writer # Use simple concatenation approach - load and merge all frames sequentially
writer = StreamingVideoWriter( all_frames = []
output_path=output_path,
fps=self.video_info['fps'],
audio_source=audio_source
)
try: try:
# Process each chunk without accumulation # Process each chunk without accumulation
for i, chunk_file in enumerate(chunk_files): for i, chunk_file in enumerate(chunk_files):
print(f"📼 Processing chunk {i+1}/{len(chunk_files)}: {chunk_file.name}") print(f"📼 Loading chunk {i+1}/{len(chunk_files)}: {chunk_file.name}")
# Load chunk (this is the only copy in memory) # Load chunk (this is the only copy in memory)
chunk_data = np.load(str(chunk_file)) chunk_data = np.load(str(chunk_file))
frames = chunk_data['frames'].tolist() # Convert to list of arrays frames = chunk_data['frames'].tolist() # Convert to list of arrays
chunk_data.close() chunk_data.close()
# Write chunk with streaming writer # Handle overlap blending (simple approach - skip overlapping frames from previous chunks)
writer.write_chunk( if i > 0 and overlap_frames > 0:
frames=frames, # Skip the first overlap_frames from this chunk (they overlap with previous)
chunk_index=i, frames = frames[overlap_frames:]
overlap_frames=overlap_frames if i > 0 else 0, print(f" ✂️ Skipped {overlap_frames} overlapping frames")
blend_with_previous=(i > 0 and overlap_frames > 0)
)
# Immediately free memory # Add frames to final sequence
all_frames.extend(frames)
print(f" ✅ Added {len(frames)} frames (total: {len(all_frames)})")
# Immediately free chunk memory
del frames, chunk_data del frames, chunk_data
# Delete chunk file to free disk space # Delete chunk file to free disk space
@@ -443,16 +439,67 @@ class VideoProcessor:
# Aggressive cleanup every chunk # Aggressive cleanup every chunk
self._aggressive_memory_cleanup(f"After processing chunk {i}") self._aggressive_memory_cleanup(f"After processing chunk {i}")
# Finalize the video # Save final video using existing method
writer.finalize() print(f"📹 Saving final video with {len(all_frames)} frames...")
self.save_video(all_frames, output_path)
# Add audio if provided
if audio_source:
self._add_audio_to_video(output_path, audio_source)
except Exception as e: except Exception as e:
print(f"❌ Streaming merge failed: {e}") print(f"❌ Streaming merge failed: {e}")
writer.cleanup() # Cleanup
if 'all_frames' in locals():
del all_frames
gc.collect()
raise raise
finally:
# Cleanup
if 'all_frames' in locals():
del all_frames
gc.collect()
print(f"✅ Streaming merge complete: {output_path}") print(f"✅ Streaming merge complete: {output_path}")
def _add_audio_to_video(self, video_path: str, audio_source: str):
"""Add audio to video using ffmpeg"""
import subprocess
import tempfile
try:
# Create temporary file for output with audio
temp_path = Path(video_path).with_suffix('.temp.mp4')
cmd = [
'ffmpeg', '-y',
'-i', str(video_path), # Input video (no audio)
'-i', str(audio_source), # Input audio source
'-c:v', 'copy', # Copy video without re-encoding
'-c:a', 'aac', # Encode audio as AAC
'-map', '0:v:0', # Map video from first input
'-map', '1:a:0', # Map audio from second input
'-shortest', # Match shortest stream duration
str(temp_path)
]
print(f"🎵 Adding audio: {audio_source}{video_path}")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"⚠️ Audio addition failed: {result.stderr}")
# Keep original video without audio
return
# Replace original with audio version
Path(video_path).unlink()
temp_path.rename(video_path)
print(f"✅ Audio added successfully")
except Exception as e:
print(f"⚠️ Could not add audio: {e}")
def merge_overlapping_chunks(self, def merge_overlapping_chunks(self,
chunk_results: List[List[np.ndarray]], chunk_results: List[List[np.ndarray]],
overlap_frames: int) -> List[np.ndarray]: overlap_frames: int) -> List[np.ndarray]: