Skip to content

Instantly share code, notes, and snippets.

@gordinmitya
Created September 30, 2023 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gordinmitya/2b89c2a9bc803e8c82b4a6c0a3ea0c86 to your computer and use it in GitHub Desktop.
Save gordinmitya/2b89c2a9bc803e8c82b4a6c0a3ea0c86 to your computer and use it in GitHub Desktop.
Player plays half-transparent video on top of other windows
"""
sudo apt install libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-4.0
pip install pycairo PyGObject opencv-python
"""
import cv2
import gi
import numpy as np
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
class VideoWindow(Gtk.Window):
def __init__(self):
super(VideoWindow, self).__init__()
self.set_decorated(False)
self.set_position(Gtk.WindowPosition.NONE)
self.move(0, 0)
screen = self.get_screen()
visual = screen.get_rgba_visual()
if visual and screen.is_composited():
self.set_visual(visual)
self.set_app_paintable(True)
self.connect("draw", self.area_draw)
GLib.timeout_add(33, self.update_frame)
self.dst = None
self.open_video()
visual = screen.get_rgba_visual()
print(f'Visual: {visual}, Composited: {screen.is_composited()}')
if visual and screen.is_composited():
self.set_visual(visual)
else:
print("Transparency not supported")
def open_video(self):
self.color_cap = cv2.VideoCapture('color.mp4')
self.alpha_cap = cv2.VideoCapture('alpha.mp4')
def area_draw(self, widget, cr):
if self.dst is not None:
height, width, _ = self.dst.shape
self.set_size_request(width, height)
dst_gtk = GdkPixbuf.Pixbuf.new_from_data(
self.dst.tobytes(), GdkPixbuf.Colorspace.RGB, True, 8, width, height, width * 4
)
Gdk.cairo_set_source_pixbuf(cr, dst_gtk, 0, 0)
cr.paint()
def update_frame(self):
ret_color, color_frame = self.color_cap.read()
ret_alpha, alpha_frame = self.alpha_cap.read()
if not ret_color or not ret_alpha:
self.open_video()
ret_color, color_frame = self.color_cap.read()
ret_alpha, alpha_frame = self.alpha_cap.read()
assert ret_color and ret_alpha
# Convert the alpha frame to single channel
alpha = cv2.cvtColor(alpha_frame, cv2.COLOR_BGR2GRAY)
# Merge the color and alpha channels
b, g, r = cv2.split(color_frame)
rgba = [r, g, b, alpha]
self.dst = cv2.merge(rgba, 4)
self.queue_draw()
return True
if __name__ == "__main__":
win = VideoWindow()
win.show_all()
Gtk.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment