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:
os
cv2
(OpenCV)subprocess
time
signal
pyautogui
numpy
(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.