# app.py - run with: streamlit run app.py import streamlit as st import cv2 import numpy as np import os from moviepy.editor import VideoFileClip import tempfile st.title("Video to Cartoon/Animated Style Converter (Keep Original Sound)") st.write("Uploads video → makes cartoon look → keeps your audio 100% same") uploaded_file = st.file_uploader("Upload video (mp4 recommended)", type=["mp4", "mov", "avi"]) if uploaded_file is not None: # Save uploaded video temporarily tfile = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") tfile.write(uploaded_file.read()) video_path = tfile.name st.video(video_path) if st.button("Convert to Cartoon Style"): with st.spinner("Processing... (may take 1–5 min depending on length)"): try: # Extract audio clip = VideoFileClip(video_path) audio_path = "temp_audio.mp3" clip.audio.write_audiofile(audio_path, codec='mp3') # Open video cap = cv2.VideoCapture(video_path) fps = cap.get(cv2.CAP_PROP_FPS) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc(*'mp4v') out_path = "cartoon_output.mp4" out = cv2.VideoWriter(out_path, fourcc, fps, (width, height)) frame_count = 0 progress = st.progress(0) while cap.isOpened(): ret, frame = cap.read() if not ret: break # Simple cartoon effect gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray, 5) edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) color = cv2.bilateralFilter(frame, 9, 250, 250) cartoon = cv2.bitwise_and(color, color, mask=edges) out.write(cartoon) frame_count += 1 progress.progress(min(frame_count / (cap.get(cv2.CAP_PROP_FRAME_COUNT) or 1), 1.0)) cap.release() out.release() # Merge original audio back final_clip = VideoFileClip(out_path) final_clip = final_clip.set_audio(VideoFileClip(video_path).audio) final_output = "final_animated_video.mp4" final_clip.write_videofile(final_output, codec="libx264", audio_codec="aac") st.success("Done!") st.video(final_output) # Clean up os.remove(video_path) os.remove(audio_path) os.remove(out_path) except Exception as e: st.error(f"Error: {e}") st.info("This is basic cartoon filter (not true 3D). For real 3D animation try DeepMotion, GoEnhance, or Krikey AI online.")