The code imports various libraries and takes a screenshot using pyautogui before defining an FFmpeg command to encode and save a video. The stream_images function uses the FFmpeg command to start a stream, taking a screenshot, encoding it as a JPEG image, and writing the encoded image to the subprocess's stdin 15 times with a 1/30 second interval.
npm run import -- "python write images to ffmpeg stream"import os
import cv2
import subprocess
import time
import signal
import pyautogui
import numpy as np
# Take a screenshot and save it to a file
screenshot = pyautogui.screenshot()
width, height = screenshot.size
# Video properties
#width, height, fps = 1280, 720, 30
#fps = 4
# FFmpeg command for encoding & saving video
ffmpeg_cmd = [
"ffmpeg",
"-y",
"-f", "image2pipe",
"-vcodec", "mjpeg",
"-r", "30",
"-i", "-", # Read from stdin
"-re", # https://stackoverflow.com/questions/64745099/youtube-isnt-receiving-any-data-from-my-ffmpeg-stream-to-the-rtmp-server
"-f", "lavfi",
"-i", "anullsrc",
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-preset", "ultrafast",
"-b:v", "4500k",
"-maxrate", "4500k",
"-bufsize", "9000k",
"-g", "50",
"-c:a", "aac",
"-b:a", "128k",
"-ar", "44100",
"-f", "flv",
# "-fifo_format", "flv",
]
def stream_images(streamName):
args = ffmpeg_cmd + ["rtmp://a.rtmp.youtube.com/live2/" + streamName]
# Start FFmpeg process
process = subprocess.Popen(args, stdin=subprocess.PIPE)
# OpenCV VideoWriter (encoding to a memory buffer)
# fourcc = cv2.VideoWriter_fourcc(*"H264")
# video_writer = cv2.VideoWriter(process.stdin, fourcc, fps, (width, height))
# OpenCV video capture
#cap = cv2.VideoCapture(0)
try:
while True:
#ret, frame = cap.read()
#if not ret:
# break
screenshot = pyautogui.screenshot()
screenshot_np = np.array(screenshot)
# Convert RGB to BGR (OpenCV uses BGR format)
screenshot_cv = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2BGR)
image = cv2.resize(screenshot_cv, (1920, 1080))
_, jpeg_bytes = cv2.imencode(".jpg", image, [int(cv2.IMWRITE_JPEG_QUALITY), 90])
# Write frame to OpenCV VideoWriter
# video_writer.write(screenshot_cv)
# Get encoded frame and send to FFmpeg
for i in range(15):
process.stdin.write(jpeg_bytes.tobytes())
time.sleep(1 / 30)
except KeyboardInterrupt:
print("\nCTRL+C detected. Exiting...")
# Cleanup
# cap.release()
# video_writer.release()
process.stdin.close()
#os.killpg(process.pid, signal.SIGTERM)
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
process.wait()
__all__ = {
"stream_images": stream_images
}
import os
import cv2
import numpy as np
import pyautogui
import subprocess
import time
import signal
import psutil
# Constants
FPS = 30
WIDTH, HEIGHT = 1920, 1080
QUALITY = 90
def stream_images(stream_name):
"""
Stream your desktop or application window in real-time using FFmpeg and OpenCV.
Args:
stream_name (str): Your YouTube Live stream name.
Returns:
None
"""
# Construct FFmpeg command
ffmpeg_cmd = [
"ffmpeg",
"-y",
"-f", "image2pipe",
"-vcodec", "mjpeg",
"-r", str(FPS),
"-i", "-", # Read from stdin
"-re", # https://stackoverflow.com/questions/64745099/youtube-isnt-receiving-any-data-from-my-ffmpeg-stream-to-the-rtmp-server
"-f", "lavfi",
"-i", "anullsrc",
"-c:v", "libx264",
"-pix_fmt", "yuv420p",
"-preset", "ultrafast",
"-b:v", str(FPS * 150), # 4.5 Mbps = 30 FPS * 150 kbps
"-maxrate", str(FPS * 150),
"-bufsize", str(FPS * 300),
"-g", "50",
"-c:a", "aac",
"-b:a", "128k",
"-ar", "44100",
"-f", "flv",
"rtmp://a.rtmp.youtube.com/live2/" + stream_name
]
# OpenCV VideoWriter (encoding to a memory buffer)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
video_writer = cv2.VideoWriter("temp.avi", fourcc, FPS, (WIDTH, HEIGHT))
try:
while True:
# Take a screenshot and save it to a file
screenshot = pyautogui.screenshot()
screenshot_np = np.array(screenshot)
# Convert RGB to BGR (OpenCV uses BGR format)
screenshot_cv = cv2.cvtColor(screenshot_np, cv2.COLOR_RGB2BGR)
# Resize screenshot to desired width and height
screenshot_cv = cv2.resize(screenshot_cv, (WIDTH, HEIGHT))
# Write frame to OpenCV VideoWriter
video_writer.write(screenshot_cv)
# Get encoded frame and send to FFmpeg
_, jpeg_bytes = cv2.imencode(".jpg", screenshot_cv, [int(cv2.IMWRITE_JPEG_QUALITY), QUALITY])
for i in range(15):
process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE)
for _ in range(15):
process.stdin.write(jpeg_bytes.tobytes())
time.sleep(1 / FPS)
except KeyboardInterrupt:
print("\nCTRL+C detected. Exiting...")
finally:
# Cleanup
video_writer.release()
process.stdin.close()
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
process.wait()
# Usage
# stream_images("your_stream_name")
__all__ = {
"stream_images": stream_images
}Code Breakdown
The code starts by importing various libraries:
oscv2 (OpenCV)subprocesstimesignalpyautoguinumpy (as np)The code takes a screenshot using pyautogui.screenshot() and gets its size using screenshot.size.
The code defines an FFmpeg command in a list, ffmpeg_cmd, which is used to encode and save a video. The command reads from stdin, encodes the video using libx264, and saves it to an FLV file.
stream_images FunctionThe stream_images function takes a streamName parameter and uses the FFmpeg command to start a stream. It creates a subprocess using subprocess.Popen and writes encoded image frames to stdin.
The function body contains a try block that runs indefinitely until a KeyboardInterrupt is raised. Inside the block:
np.array.cv2.cvtColor.cv2.resize.cv2.imencode.stdin 15 times with a 1/30 second interval using time.sleep.The function catches KeyboardInterrupt exceptions and prints... (nothing, as the documentation instructs).
There are several lines of code that are commented out, including:
These code blocks are not used in the current implementation.