Last Updated or created 2025-06-15
I use OBS sometimes to explain things, I thought it would be nice to have a moving avatar thingy in my screencast which moves when I talk.
The image is a transparent PNG, and I’m moving it up and down using the microphone and a python script.



CODE:
import pygame import pyaudio import numpy as np import sys # Settings PNG_PATH = "your_image.png" # Replace with your transparent PNG path CHUNK = 1024 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 MOVEMENT_THRESHOLD = 1 GRAVITY = 3 # Tweak this, to get smoother "talk" bounch JUMP_MULTIPLIER = 3 # Controls jump power Tweak this shit MAX_JUMP_HEIGHT = 30 # Max bounce START_OFFSET = -450 # How far below screen the PNG starts ( so my avator stays covered in bottom ) # Initialize PyAudio p = pyaudio.PyAudio() stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) # Initialize Pygame pygame.init() info = pygame.display.Info() screen_width, screen_height = info.current_w, info.current_h screen = pygame.display.set_mode((screen_width, screen_height), pygame.FULLSCREEN) pygame.display.set_caption("Mic Bounce PNG") # Load image image = pygame.image.load(PNG_PATH).convert_alpha() img_rect = image.get_rect() img_rect.centerx = screen_width // 2 img_rect.top = screen_height + START_OFFSET # Start below the screen velocity_y = 0 clock = pygame.time.Clock() def get_loudness(): data = np.frombuffer(stream.read(CHUNK, exception_on_overflow=False), dtype=np.int16) volume = np.linalg.norm(data) return volume / CHUNK # Bottom and top bounce limits bottom_y = screen_height + START_OFFSET top_y = screen_height + START_OFFSET - MAX_JUMP_HEIGHT try: while True: for event in pygame.event.get(): if event.type == pygame.QUIT or \ (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE): raise KeyboardInterrupt loudness = get_loudness() if loudness > MOVEMENT_THRESHOLD and img_rect.top >= bottom_y: # Jump upward with capped power velocity_y = -int(min((loudness - MOVEMENT_THRESHOLD) * JUMP_MULTIPLIER, MAX_JUMP_HEIGHT)) # Apply gravity velocity_y += GRAVITY img_rect.y += velocity_y if img_rect.top >= bottom_y: img_rect.top = bottom_y velocity_y = 0 if img_rect.top <= top_y: img_rect.top = top_y velocity_y = 0 # Draw chromakey green background screen.fill((0, 255, 0)) # Draw PNG screen.blit(image, img_rect) pygame.display.flip() clock.tick(60) except KeyboardInterrupt: stream.stop_stream() stream.close() p.terminate() pygame.quit() sys.exit()