Вот мой код:
```py
# app.py

import os
import threading
import time
import uuid
import math

import cv2
import mediapipe as mp
import numpy as np
from collections import deque
from flask import Flask, request, jsonify
from flask_socketio import SocketIO, emit, join_room, leave_room
import gradio as gr
import requests  # Перемещено в начало

# Импорт DeepFitClassifier
from DeepFit.DeepFitClassifier import DeepFitClassifier  # Убедитесь, что путь корректный

# Инициализация Flask и SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins="*")

# Максимальное количество одновременных сессий
MAX_SESSIONS = 10

# Хранилище сессий
sessions = {}
sessions_lock = threading.Lock()

# Маркировка для Mediapipe
mpDraw = mp.solutions.drawing_utils
mpPose = mp.solutions.pose

# Функции для обработки видео
def set_pose_parameters():
    mode = False
    complexity = 1
    smooth_landmarks = True
    enable_segmentation = False
    smooth_segmentation = True
    detectionCon = 0.5
    trackCon = 0.5
    pose = mpPose.Pose(mode, complexity, smooth_landmarks,
                       enable_segmentation, smooth_segmentation,
                       detectionCon, trackCon)
    return pose

def get_position(results, height, width, draw=False):
    landmark_list = []
    if results.pose_landmarks:
        for id, landmark in enumerate(results.pose_landmarks.landmark):
            landmark_pixel_x, landmark_pixel_y = int(landmark.x * width), int(landmark.y * height)
            landmark_list.append([id, landmark_pixel_x, landmark_pixel_y])
            if draw:
                cv2.circle(None, (landmark_pixel_x, landmark_pixel_y), 5, (255, 0, 0), cv2.FILLED)  # Placeholder
    return landmark_list

def get_angle(landmark_list, point1, point2, point3):
    try:
        x1, y1 = landmark_list[point1][1:]
        x2, y2 = landmark_list[point2][1:]
        x3, y3 = landmark_list[point3][1:]
    except IndexError:
        return 0  # Возвращать 0, если ключевая точка отсутствует

    angle = math.degrees(math.atan2(y3 - y2, x3 - x2) -
                         math.atan2(y1 - y2, x1 - x2))

    # Обработка крайних случаев углов
    if angle < 0:
        angle += 360
        if angle > 180:
            angle = 360 - angle
    elif angle > 180:
        angle = 360 - angle

    return int(angle)

# Обработка видео для конкретной сессии
def video_processing(session_id, video_path=None, use_webcam=False):
    pose = set_pose_parameters()
    clf = DeepFitClassifier('DeepFit/deepfit_classifier_v3.tflite')  # Убедитесь, что путь корректный

    if use_webcam:
        cap = cv2.VideoCapture(0)
        if not cap.isOpened():
            socketio.emit('error', {'message': 'Не удалось открыть веб-камеру.'}, room=session_id)
            return
    else:
        if not video_path or not os.path.exists(video_path):
            socketio.emit('error', {'message': 'Неверный путь к видеофайлу.'}, room=session_id)
            return
        cap = cv2.VideoCapture(video_path)

    count = 0
    direction = 0
    form = 0
    feedback = "Bad Form. Correct Posture."
    frame_queue = deque(maxlen=250)

    while cap.isOpened():
        ret, img = cap.read()
        if not ret:
            break

        height, width = img.shape[:2]
        results = pose.process(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        landmark_list = get_position(results, height, width, draw=False)

        data = {}
        if len(landmark_list) != 0:
            elbow_angle = get_angle(landmark_list, 11, 13, 15)
            shoulder_angle = get_angle(landmark_list, 13, 11, 23)
            hip_angle = get_angle(landmark_list, 11, 23, 25)

            pushup_success_percentage = int(np.interp(elbow_angle, (90, 160), (0, 100)))
            pushup_progress_bar = int(np.interp(elbow_angle, (90, 160), (380, 50)))

            # Проверка начальной формы
            if elbow_angle > 160 and shoulder_angle > 40 and hip_angle > 160:
                form = 1

            # Полный цикл выполнения отжиманий
            if form == 1:
                if pushup_success_percentage == 0:
                    if elbow_angle <= 90 and hip_angle > 160:
                        feedback = "Go Up"
                        if direction == 0:
                            count += 0.5
                            direction = 1
                    else:
                        feedback = "Bad Form. Correct Posture."

                if pushup_success_percentage == 100:
                    if elbow_angle > 160 and shoulder_angle > 40 and hip_angle > 160:
                        feedback = "Go Down"
                        if direction == 1:
                            count += 0.5
                            direction = 0
                    else:
                        feedback = "Bad Form. Correct Posture."

            # Формирование данных для отправки клиенту
            data = {
                'count': int(count),
                'feedback': feedback,
                'pushup_success_percentage': int(pushup_success_percentage),
                'pushup_progress_bar': int(pushup_progress_bar),
            }

        # Обновление данных сессии
        with sessions_lock:
            if session_id in sessions:
                sessions[session_id]['data'] = data

        # Отправка данных через SocketIO
        socketio.emit('video_frame', data, room=session_id)

        # Ограничение FPS (например, 30 FPS)
        socketio.sleep(1/30)

    cap.release()
    pose.close()
    socketio.emit('processing_complete', {'message': 'Processing complete.'}, room=session_id)

    # Очистка данных сессии
    with sessions_lock:
        if session_id in sessions:
            sessions.pop(session_id, None)

# Обработчики SocketIO событий
@socketio.on('connect')
def handle_connect():
    print('Client connected')

@socketio.on('disconnect')
def handle_disconnect():
    print('Client disconnected')
    # Очистка сессии при отключении
    for session_id, session in list(sessions.items()):
        if session['sid'] == request.sid:
            with sessions_lock:
                sessions.pop(session_id, None)
            break

@socketio.on('join')
def handle_join(data):
    session_id = data.get('session_id')
    if not session_id:
        # Создание нового session_id
        session_id = str(uuid.uuid4())
        with sessions_lock:
            if len(sessions) >= MAX_SESSIONS:
                emit('error', {'message': 'Максимальное количество сессий достигнуто.'})
                return
            sessions[session_id] = {
                'sid': request.sid,
                'active': False,
                'data': {}
            }
    join_room(session_id)
    emit('joined', {'session_id': session_id})
    print(f'Client joined session: {session_id}')

@socketio.on('start_video')
def handle_start_video(data):
    session_id = data.get('session_id')
    use_webcam = data.get('use_webcam', False)

    with sessions_lock:
        if session_id not in sessions:
            emit('error', {'message': 'Session ID не найден.'})
            return
        if sessions[session_id]['active']:
            emit('error', {'message': 'Видео уже обрабатывается.'})
            return
        sessions[session_id]['active'] = True

    # Запуск обработки видео в отдельном потоке
    thread = threading.Thread(target=video_processing, args=(session_id, None, use_webcam))
    thread.start()

@socketio.on('stop_video')
def handle_stop_video(data):
    session_id = data.get('session_id')
    with sessions_lock:
        if session_id not in sessions:
            emit('error', {'message': 'Session ID не найден.'})
            return
        sessions[session_id]['active'] = False
    emit('stopped', {'message': 'Видео остановлено.'})

# API эндпоинты для Gradio
@app.route('/api/get_latest/<session_id>', methods=['GET'])
def get_latest(session_id):
    with sessions_lock:
        session = sessions.get(session_id)
        if not session:
            return jsonify({'error': 'Session ID не найден.'}), 404
        data = session.get('data', {})
    return jsonify(data)

@app.route('/api/join', methods=['POST'])
def api_join():
    print("JOIN!!!!!!")
    with sessions_lock:
        if len(sessions) >= MAX_SESSIONS:
            return jsonify({'error': 'Максимальное количество сессий достигнуто.'}), 400
        session_id = str(uuid.uuid4())
        sessions[session_id] = {
            'sid': None,
            'active': False,
            'data': {}
        }
    return jsonify({'session_id': session_id})

@app.route('/api/start_video', methods=['POST'])
def api_start_video():
    data = request.json
    session_id = data.get('session_id')
    use_webcam = data.get('use_webcam', False)

    with sessions_lock:
        if session_id not in sessions:
            return jsonify({'error': 'Session ID не найден.'}), 404
        if sessions[session_id]['active']:
            return jsonify({'error': 'Видео уже обрабатывается.'}), 400
        sessions[session_id]['active'] = True

    # Запуск обработки видео в отдельном потоке
    thread = threading.Thread(target=video_processing, args=(session_id, None, use_webcam))
    thread.start()

    return jsonify({'message': 'Видео начато.'})

@app.route('/api/stop_video', methods=['POST'])
def api_stop_video():
    data = request.json
    session_id = data.get('session_id')

    with sessions_lock:
        if session_id not in sessions:
            return jsonify({'error': 'Session ID не найден.'}), 404
        sessions[session_id]['active'] = False

    return jsonify({'message': 'Видео остановлено.'})

# Gradio интерфейс
def gradio_interface():
    with gr.Blocks(title="Push-Up Tracker") as demo:
        gr.Markdown("## Push-Up Tracker")

        with gr.Row():
            connect_btn = gr.Button("Подключиться к сессии")
            session_id_text = gr.Textbox(label="Session ID", interactive=False)

        with gr.Row():
            start_btn = gr.Button("Начать поток видео (Веб-камера)")
            stop_btn = gr.Button("Остановить поток видео")

        with gr.Row():
            reps_display = gr.Number(label="Количество отжиманий", interactive=False)
            feedback_display = gr.Textbox(label="Обратная связь", interactive=False)

        with gr.Row():
            percentage_display = gr.Number(label="Успешность отжиманий (%)", interactive=False)
            progress_display = gr.HTML(label="Прогресс-бар")

        def connect():
            try:
                response = requests.post("http://localhost:5000/api/join")
                if response.status_code == 200:
                    session_id = response.json().get('session_id')
                    return session_id
                else:
                    return "Ошибка подключения."
            except Exception as e:
                return f"Ошибка подключения: {e}"

        def start_video(session_id):
            if not session_id or session_id.startswith("Ошибка"):
                return "Нет активной сессии."
            try:
                response = requests.post("http://localhost:5000/api/start_video", json={
                    'session_id': session_id,
                    'use_webcam': True
                })
                if response.status_code == 200:
                    return "Видео начато."
                else:
                    return response.json().get('error', 'Ошибка при запуске видео.')
            except Exception as e:
                return f"Ошибка при запуске видео: {e}"

        def stop_video(session_id):
            if not session_id or session_id.startswith("Ошибка"):
                return "Нет активной сессии."
            try:
                response = requests.post("http://localhost:5000/api/stop_video", json={
                    'session_id': session_id
                })
                if response.status_code == 200:
                    return "Видео остановлено."
                else:
                    return response.json().get('error', 'Ошибка при остановке видео.')
            except Exception as e:
                return f"Ошибка при остановке видео: {e}"

        def update_data(session_id):
            if not session_id or session_id.startswith("Ошибка"):
                return 0, "", 0, ""
            try:
                response = requests.get(f"http://localhost:5000/api/get_latest/{session_id}")
                if response.status_code == 200:
                    data = response.json()
                    count = data.get('count', 0)
                    feedback = data.get('feedback', "")
                    percentage = data.get('pushup_success_percentage', 0)
                    progress = f"""
                    <div style="position: relative; width: 50px; height: 400px; border: 1px solid #000;">
                        <div style="position: absolute; bottom: 0; width: 100%; height: {percentage * 4}px; background-color: green;"></div>
                    </div>
                    """
                    return count, feedback, percentage, progress
                else:
                    return 0, "Нет данных.", 0, ""
            except Exception as e:
                return 0, f"Ошибка обновления данных: {e}", 0, ""

        def live_update(session_id):
            while True:
                yield update_data(session_id)
                time.sleep(0.1)  # Уменьшено время ожидания для более быстрых обновлений

        connect_btn.click(fn=connect, outputs=session_id_text)
        start_btn.click(fn=start_video, inputs=session_id_text, outputs=None)
        stop_btn.click(fn=stop_video, inputs=session_id_text, outputs=None)

        demo.load(live_update, session_id_text, [reps_display, feedback_display, percentage_display, progress_display])

    demo.launch(share=True)

# Запуск Flask и Gradio в отдельных потоках
if __name__ == '__main__':
    # Запуск Flask сервера в отдельном демоническом потоке
    flask_thread = threading.Thread(target=lambda: socketio.run(app, host='0.0.0.0', port=5000, use_reloader=False))
    flask_thread.daemon = True  # Устанавливаем поток как демонический

    # Дождаться запуска Flask сервера
    time.sleep(2)

    # Запуск Gradio интерфейса в основном потоке
    gradio_interface()
    flask_thread.start()

    while True:
        time.sleep(1)
```
Видео с камеры не отображается. Исправь и приведи полный обновленный код