Skip to main content
Version: 0.0.x

Transform Video - Python

This guide will help you understand how to transform video frames in real-time using the VideoSDK. In this example, we'll transform video frames into a cartoon-like appearance.

Prerequisites​

  1. Install necessary libraries:
    pip install videosdk python-dotenv opencv-python av
  2. Create a .env file and add your VideoSDK token, meeting ID, and name:
    VIDEOSDK_TOKEN=your_token
    MEETING_ID=your_meeting_id
    NAME=your_name

Code Breakdown​

Imports and Constants​

We start by importing necessary libraries and loading environment variables in transform_video.py file:

import asyncio
import os
from videosdk import MeetingConfig, VideoSDK, Participant, Stream, MeetingEventHandler, ParticipantEventHandler, CustomVideoTrack, Meeting
import mediapipe as mp
import cv2
from av import VideoFrame

from dotenv import load_dotenv
load_dotenv()
VIDEOSDK_TOKEN = os.getenv("VIDEOSDK_TOKEN")
MEETING_ID = os.getenv("MEETING_ID")
NAME = os.getenv("NAME")
loop = asyncio.get_event_loop()

meeting: Meeting = None

Transform Video Processor​

This processor performs frame detection on each video frame and draws the cartoon-like anime and return the frame:

class TransformVideoProcessor():
def __init__(self) -> None:
print("Processor initialized")

def process(self, frame: VideoFrame) -> VideoFrame:
img = frame.to_ndarray(format="bgr24")

# prepare color
img_color = cv2.pyrDown(cv2.pyrDown(img))
for _ in range(6):
img_color = cv2.bilateralFilter(img_color, 9, 9, 7)
img_color = cv2.pyrUp(cv2.pyrUp(img_color))

# prepare edges
img_edges = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img_edges = cv2.adaptiveThreshold(
cv2.medianBlur(img_edges, 7),
255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY,
9,
2,
)
img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB)

# combine color and edges
img = cv2.bitwise_and(img_color, img_edges)

# rebuild a VideoFrame, preserving timing information
new_frame = VideoFrame.from_ndarray(img, format="bgr24")
new_frame.pts = frame.pts
new_frame.time_base = frame.time_base

return new_frame

CustomVideoTrack​

Define a custom video track that will run the above processor when new frame received.

class ProcessedVideoTrack(CustomVideoTrack):
"""
A video stream track that transforms frames from an another track.
"""

kind = "video"

def __init__(self, track):
super().__init__() # don't forget this!
self.track = track
self.processor = TransformVideoProcessor()

async def recv(self):
frame = await self.track.recv()
new_frame = self.processor.process(frame)
return new_frame

Process on stream available​

This function applies the ProcessedVideoTrack to a available video track:

def process_video(track: CustomVideoTrack):
global meeting
meeting.add_custom_video_track(
track=ProcessedVideoTrack(track=track)
)

Event Handlers​

Define event handlers to handle meeting and participant events:

class MyMeetingEventHandler(MeetingEventHandler):
def __init__(self):
super().__init__()

def on_meeting_left(self, data):
print("on_meeting_left")

def on_participant_joined(self, participant: Participant):
participant.add_event_listener(
MyParticipantEventHandler(participant_id=participant.id)
)

def on_participant_left(self, participant: Participant):
print("on_participant_left")

class MyParticipantEventHandler(ParticipantEventHandler):
def __init__(self, participant_id: str):
super().__init__()
self.participant_id = participant_id

def on_stream_enabled(self, stream: Stream):
print("on_stream_enabled: " + stream.kind)
if stream.kind == "video":
process_video(track=stream.track)

def on_stream_disabled(self, stream: Stream):
print("on_stream_disabled")

Main Function​

Initialize the meeting and start the event loop:

def main():
global meeting
# Example usage:
meeting_config = MeetingConfig(
meeting_id=MEETING_ID,
name=NAME,
mic_enabled=False,
webcam_enabled=False,
token=VIDEOSDK_TOKEN,
)
meeting = VideoSDK.init_meeting(**meeting_config)

print("adding event listener...")
meeting.add_event_listener(MyMeetingEventHandler())

print("joining into meeting...")
meeting.join()

if __name__ == "__main__":
main()
loop.run_forever()

Running the Code​

To run the code, simply execute the script:

python transform_video.py

This script will join the meeting specified by MEETING_ID with the provided VIDEOSDK_TOKEN and NAME, and transform video frames in real-time using the cartoon filter.

Feel free to modify the transformation logic inside the process method of the VideoTransformTrack class to apply different kinds of video transformations.

Output​

tip

Check out this example code on GitHub, to Explore More Transformation like cartoon, edges, blur, face-blur, rotate

API Reference​

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord