Automating Stockfish Evaluations for Chess Videos with Python
Image extracted from: https://youtube.com/@xadrezbrasil

Automating Stockfish Evaluations for Chess Videos with Python

As a chess content creator on YouTube, I always look for ways to enhance the viewing experience. One of the biggest challenges? Displaying Stockfish evaluations dynamically without spending hours manually editing graphics.

To solve this, I built a Python-based automation tool that: ? Detects the chessboard in video frames. ? Extracts the board position (FEN) automatically. ? Runs deep Stockfish evaluations (Depth 26). ? Generates SRT subtitles with evaluation bars for seamless overlay.

This allows viewers to toggle Stockfish evals on/off in the YouTube subtitle settings, letting them choose between pure analysis or engine-assisted insights. ????

?? GitHub Repo: github.com/rafaelvleite/youtube-eval-bar


?? Why Build This?

Manually adding evaluation graphics is slow and tedious. This system fully automates the process, making it easier to: ?? Analyze games efficiently in recorded videos. ?? Provide evaluation insights dynamically without editing. ?? Let viewers choose whether to see evals or just enjoy the commentary.


?? How It Works

The system follows four key steps:

1?? Frame Extraction & Chessboard Detection

The script analyzes video frames to detect the chessboard using OpenCV. Here’s the core function that finds the board in each frame:

import cv2
import numpy as np

def detect_chessboard(frame):
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 150)
    contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    largest_square = None
    max_area = 0

    for cnt in contours:
        approx = cv2.approxPolyDP(cnt, 0.02 * cv2.arcLength(cnt, True), True)
        if len(approx) == 4:
            area = cv2.contourArea(approx)
            if area > max_area:
                max_area = area
                largest_square = approx

    if largest_square is not None:
        x, y, w, h = cv2.boundingRect(largest_square)
        return frame[y:y+h, x:x+w]

    return None  # No chessboard detected        

2?? Extracting FEN from Video Frames

Once the board is detected, we convert it into FEN notation (the standard way to describe a chess position). This uses a deep learning model from board_to_fen.predict:

from PIL import Image
from board_to_fen.predict import get_fen_from_image

def extract_fen_from_frame(frame):
    board_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    detected_fen = get_fen_from_image(board_image)
    return detected_fen.split(" ")[0]  # Only board layout        

It also automatically detects board orientation (White or Black) using OCR.


3?? Stockfish Evaluation at Depth 26

The extracted FEN is passed to Stockfish, the strongest open-source chess engine:

import chess
import chess.engine

STOCKFISH_PATH = "/opt/homebrew/bin/stockfish"

def evaluate_position(fen):
    with chess.engine.SimpleEngine.popen_uci(STOCKFISH_PATH) as engine:
        board = chess.Board(fen)
        info = engine.analyse(board, chess.engine.Limit(depth=26))
        eval_score = info["score"].white().score(mate_score=10000) / 100
    return eval_score        

The evaluation is stored, ready to be used in the subtitles.


4?? Generating SRT Subtitles with Evaluation Bars

The final step is generating a subtitle file (SRT) containing: ? A visual evaluation bar ? Numeric evaluation in full-width characters ? Time-synced entries

def draw_eval_bar(eval_score):
    BAR_LENGTH = 24
    ratio = min(1.0, max(0.0, (eval_score + 4) / 8.0))  # Normalize to range
    filled = int(round(ratio * BAR_LENGTH))
    return "▓" * filled + "?" * (BAR_LENGTH - filled)

def fullwidth_eval(eval_score):
    mapping = {'0': '0', '1': '1', '2': '2', '3': '3', '4': '4', 
               '5': '5', '6': '6', '7': '7', '8': '8', '9': '9', 
               '.': '.', '-': '-', '+': '+'}
    return "".join(mapping.get(ch, ch) for ch in f"{eval_score:+5.2f}")

def write_srt_subtitle(start_sec, end_sec, eval_score, subtitle_index, srt_file):
    start_tc = format_timecode(start_sec)
    end_tc = format_timecode(end_sec)
    bar = draw_eval_bar(eval_score)
    numeric = f"[{fullwidth_eval(eval_score)}]"
    
    srt_file.write(f"{subtitle_index}\n{start_tc} --> {end_tc}\n{bar} {numeric}\n\n")        

Example output in an SRT file:

1 00:00:10,000 --> 00:00:20,000 ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓?????? [+3.20]

This means White has a +3.20 advantage at this moment.


?? Final Output: A Fully Automated Chess Evaluation Overlay

With the generated .srt file, I can simply import it into YouTube or any video editor. The eval bar appears as subtitles, giving viewers the ability to toggle it on/off as they wish.


?? Full Project & Code

All the code for this project is available here: ?? GitHub Repo: github.com/rafaelvleite/youtube-eval-bar


?? What’s Next?

This system is already improving my chess videos, but I have plans to: ? Integrate it into live streams (Twitch/YouTube Live). ? Enhance board detection with deep learning. ? Add customization options for eval bar colors & animations.


?? Your Thoughts?

Would you use an automated Stockfish evaluation system like this for your chess videos? Let me know your thoughts & suggestions! ??????

Luiz Rolim

Seasoned Engineering Leader

3 周

Genial! Cada vez mais f?! O maneiro é que dá pra ver real time nas partidas que vc joga como ta!

回复

Genial Rafa!

Wolf Rowell

Sócio-Diretor @ Noale Energia | Engenharia e Finan?as | Professor do MBA Gest?o para o Setor Elétrico | Mestrando em Ciência da Computa??o com ênfase em Inteligência Artificial

1 个月

Grande Rafa! Que demais ... muito útil e criativo!! parabéns ??

Afonso Orgino Lenzi

| Databricks | Data Engineering |

1 个月

Amazing chess and tech content my friend!

Jairo Macedo

Msc in Economics

1 个月

Sensacional!! O melhor que temos

要查看或添加评论,请登录

Rafael Vicente Leite的更多文章

社区洞察

其他会员也浏览了