I have a flask videohosting server. I will tell you what i want from you.
This is the main directory:
app.cfg  data  db  main2.py  main.py  Procfile  readme.md  requirements.txt  run.sh  srv.sh  static  templates
this is the db:
db/hosting.sql
this is the templates folder:
about.html      base.html        error.html     feed.html   login.html   register.html  upload_avatar.html  videoback.html
add_video.html  edit_video.html  favorite.html  index.html  people.html  search.html    user.html           video.html
this is the data folder:
__all_models.py  db_session.py         likes_resource.py  __pycache__       subscriptions_resource.py  users.py           video_form.py  videos_resource.py
avatar_form.py   dislikes_resource.py  login_form.py      register_form.py  users_arg_parser.py        users_resource.py  videos.py

This is my app2.py(i use it)
import os
import json
from passlib.context import CryptContext
from PIL import Image
from flask import Flask, render_template, url_for, redirect, request, send_from_directory, flash
from flask_login import LoginManager, login_user, current_user, logout_user
from flask_restful import Api
from data import db_session
from data.videos import Video
from data.users import User
from data.login_form import LoginForm
from data.register_form import RegisterForm
from data.video_form import VideoForm
from data.users_resource import UsersResource, UserListResource
from data.videos_resource import VideosResource, VideoListResource
from data.likes_resource import LikeResource, NotLikeResource
from data.subscriptions_resource import FollowResource, NotFollowResource
from werkzeug.utils import secure_filename
from data.avatar_form import AvatarForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'yandexlyceum_secret_key'

api = Api(app)

login_manager = LoginManager()
login_manager.init_app(app)

pwd_context = CryptContext(
    schemes=["pbkdf2_sha256"],
    default="pbkdf2_sha256",
    pbkdf2_sha256__default_rounds=30000
)


# Set the folder to store avatars
AVATAR_UPLOAD_FOLDER = os.path.join(app.root_path, 'static', 'avatars')
# Allowed extensions
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

app.config['AVATAR_UPLOAD_FOLDER'] = AVATAR_UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 2MB max upload sizes

@app.route('/favicon.ico')
def favicon():
    """Возвращает кастомную иконку страницы в браузере"""
    return send_from_directory(os.path.join(app.root_path, 'static/img'),
                               'vhs.ico', mimetype='image/vnd.microsoft.icon')


def load_user(user_id):
    """Loads the user by ID."""
    return db_sess.query(User).get(user_id)

@app.route('/upload_avatar', methods=['GET', 'POST'])
def upload_avatar():
    """Allows authenticated users to upload their avatar."""
    form = AvatarForm()
    if form.validate_on_submit():
        avatar = form.avatar.data
        # Secure the filename
        filename = secure_filename(avatar.filename)
        # Create a unique filename using user ID
        file_ext = os.path.splitext(filename)[1].lower()
        avatar_filename = f"user_{current_user.id}{file_ext}"
        avatar_path = os.path.join(app.config['AVATAR_UPLOAD_FOLDER'], avatar_filename)

        # Save the avatar temporarily
        avatar.save(avatar_path)

        # Validate and process the image
        try:
            img = Image.open(avatar_path)
            img = img.convert('RGB')  # Ensure image is in RGB
            img.thumbnail((300, 300))  # Resize to 300x300 pixels
            img.save(avatar_path, optimize=True, quality=85)  # Optimize and save
        except Exception as e:
            os.remove(avatar_path)
            flash('Неправильный формат файла!', 'danger')
            return render_template('upload_avatar.html', form=form)

        # Update user's avatar in the database
        current_user.avatar = avatar_filename
        db_sess.commit()

        flash('Аватар загружен успешно!', 'success')
        return redirect(url_for('user', user_id=current_user.id))
    else:
        if form.errors:
            # Aggregate form errors
            error_messages = '; '.join([' '.join(err) for err in form.errors.values()])
            flash(error_messages, 'danger')
    return render_template('upload_avatar.html', form=form)



@app.errorhandler(403)
def forbidden(e):
    """Возвращает кастомную страницу ошибки 403"""
    params = {
        'title': 'Доступ запрещен',
        'message': 'Похоже, у вас нет доступа к этой странице ¯\\_(ツ)_/¯',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('error.html', **params), 403

def to_int(value):
    try:
        return int(value)
    except ValueError:
        return 0  # or handle as needed

app.jinja_env.filters['to_int'] = to_int

@app.errorhandler(404)
def page_not_found(e):
    """Возвращает кастомную страницу ошибки 404"""
    params = {
        'title': 'Страница не найдена',
        'message': 'Похоже, мы не можем найти нужную вам страницу ¯\\_(ツ)_/¯',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('error.html', **params), 404


@app.errorhandler(405)
def method_not_allowed(e):
    """Возвращает кастомную страницу ошибки 405"""
    params = {
        'title': 'Метод не разрешен',
        'message': 'Похоже, этот метод не разрешен ¯\\_(ツ)_/¯',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('error.html', **params), 405


@app.errorhandler(500)
def internal_server_error(e):
    """Возвращает кастомную страницу ошибки 500"""
    params = {
        'title': 'Ошибка сервера',
        'message': 'Похоже, на сервере произошла непредвиденная ошибка ¯\\_(ツ)_/¯',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('error.html', **params), 500


@app.route('/')
@app.route('/index')
def index():
    """Возвращает домашнюю страницу"""
    all_videos = db_sess.query(Video).all()
    if len(all_videos) > 10:
        last_videos = all_videos[len(all_videos) - 10:][::-1]
    else:
        last_videos = all_videos[::-1]
    best_videos = sorted(all_videos, key=lambda x: -x.likes)[:3]
    underrated_videos = list(filter(lambda x: x.likes == 0, all_videos))
    if len(underrated_videos) > 9:
        underrated_videos = underrated_videos[len(underrated_videos) - 9:][::-1]
    else:
        underrated_videos = underrated_videos[::-1]

    params = {
        'title': 'Video Hosting Service',
        'last_videos': last_videos,
        'best_videos': best_videos,
        'underrated_videos': underrated_videos,
        'user': user,
        'db_sess': db_sess,
        'User': User,
        'Video': Video,
        'authenticated': current_user.is_authenticated,
        'all_videos': all_videos,
        'current_user': current_user
    }
    return render_template('index.html', **params)


@login_manager.user_loader
def load_user(user_id):
    """Возвращает пользователя"""
    return db_sess.query(User).get(user_id)


@app.route('/login', methods=['GET', 'POST'])
def login():
    """Возвращает страницу авторизации и авторизует пользователя"""
    if current_user.is_authenticated:
        return forbidden('')
    form = LoginForm()
    params = {
        'title': 'Авторизация',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    if form.validate_on_submit():
        user = db_sess.query(User).filter(User.login == form.login.data).first()
        if user and pwd_context.verify(form.password.data, user.password):
            login_user(user, remember=form.remember_me.data)
            return redirect('/')
        return render_template('login.html',
                               message='Неправильный логин или пароль',
                               form=form, **params)
    return render_template('login.html', form=form, **params)


@app.route('/register', methods=['GET', 'POST'])
def register():
    """Возвращает страницу регистрации и регистрирует пользователя"""
    if current_user.is_authenticated:
        return forbidden('')
    form = RegisterForm()
    params = {
        'title': 'Регистрация',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    if form.validate_on_submit():
        user = db_sess.query(User).filter(User.login == form.login.data).all()
        if user:
            return render_template('register.html',
                                   message='Пользователь с таким логином уже существует',
                                   form=form, **params)
        if form.password.data != form.repeat_password.data:
            return render_template('register.html',
                                   message='Пароли не совпадают',
                                   form=form, **params)
        user = User()
        user.login = form.login.data
        user.password = pwd_context.hash(form.password.data)
        user.name = form.name.data
        user.surname = form.surname.data
        db_sess.add(user)
        db_sess.commit()
        login_user(user, remember=form.remember_me.data)
        return redirect('/')
    return render_template('register.html', form=form, **params)


@app.route('/logout')
def logout():
    """
    Производит выход пользователя из системы, возвращает домашнюю страницу.
    Если пользователь не авторизован, возвращает страницу ошибки 403
    """
    if current_user.is_authenticated:
        logout_user()
        return redirect('/')
    else:
        return forbidden('')


@app.route('/video/<int:video_id>')
def video(video_id):
    """Возвращает страницу с видео"""
    current_video = db_sess.query(Video).get(video_id)
    if user is None:
        return page_not_found('')
    all_videos = db_sess.query(Video).all()
    if len(all_videos) > 3:
        last_videos = all_videos[len(all_videos) - 3:][::-1]
    else:
        last_videos = all_videos[::-1]
    title = current_video.title
    author_id = current_video.author
    author = db_sess.query(User).get(author_id)
    like = False
    subscription = False
    if current_user.is_authenticated:
        likes = json.loads(current_user.likes)
        subscriptions = json.loads(current_user.subscriptions)
        if video_id in likes:
            like = True
        if author_id in subscriptions:
            subscription = True
    params = {
        'title': f'{title} - {author.name} {author.surname}',
        'current_video': current_video,
        'video_id': video_id,
        'video_src': url_for("static", filename=f'vid/{video_id}.mp4'),
        'author': author,
        'like': like,
        'subscription': subscription,
        'last_videos': last_videos,
        'db_sess': db_sess,
        'User': User,
        'user': user,
        'Video': Video,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user,
        'avatar_url': url_for('static', filename=f'avatars/{author.avatar}'),  # Pass the avatar URL
    }
    return render_template('video.html', **params)


@app.route('/add_video', methods=['GET', 'POST'])
def add_video():
    """
    Возвращает страницу добавления видео если пользователь авторизован,
    иначе доступ запрещен
    """
    if not current_user.is_authenticated:
        return forbidden('')
    form = VideoForm()
    params = {
        'title': 'Добавление видео',
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    if form.validate_on_submit():
        video_file = request.files['video']
        if not video_file.filename.lower().endswith('.mp4'):
            return render_template('add_video.html',
                                   message='Данный формат видео не поддерживается. '
                                           'Пожалуйста, загрузите видео в формате mp4.',
                                   form=form, **params)
        preview_file = request.files['preview']
        if not preview_file.filename.lower().endswith('.jpg'):
            return render_template('add_video.html',
                                   message='Данный формат обложки не поддерживается. '
                                           'Пожалуйста, загрузите изображение в формате jpg.',
                                   form=form, **params)
        video = Video()
        video.title = form.title.data
        video.description = '<br>'.join(form.description.data.split('\n'))
        video.author = current_user.id
        db_sess.add(video)
        db_sess.commit()
        video_file.save(os.path.join('static/vid', f'{video.id}.mp4'))
        preview_file.save(os.path.join('static/pre', f'{video.id}.jpg'))
        with Image.open(f'static/pre/{video.id}.jpg') as preview_file:
            width, height = preview_file.size
            if width >= height:
                new_width = height * 16 // 9
                delta = (width - new_width) // 2
                preview_file = preview_file.crop((delta, 0, new_width + delta, height))
            else:
                new_height = width * 9 // 16
                delta = (height - new_height) // 2
                preview_file = preview_file.crop((0, delta, width, new_height + delta))
            preview_file.save(f'static/pre/{video.id}.jpg')
        return redirect('/')
    return render_template('add_video.html', form=form, **params)


@app.route('/edit_video/<int:video_id>', methods=['GET', 'POST'])
def edit_video(video_id):
    """
    Возвращает страницу редактирования видео
    если пользователь авторизован и является автором,
    иначе доступ запрщен
    """
    form = VideoForm()
    video = db_sess.query(Video).get(video_id)
    if not current_user.is_authenticated:
        return forbidden('')
    if not current_user.id != video.author:
        return forbidden('')

    params = {
        'title': 'Редактирование видео',
        'video': video,
        'description': '\n'.join(video.description.split('<br>')),
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    if form.validate_on_submit():
        video_file = request.files['video']
        if not video_file.filename.lower().endswith('.mp4'):
            return render_template('edit_video.html',
                                   message='Данный формат видео не поддерживается',
                                   form=form, **params)
        preview_file = request.files['preview']
        if not preview_file.filename.lower().endswith('.jpg'):
            return render_template('edit_video.html',
                                   message='Данный формат обложки не поддерживается',
                                   form=form, **params)
        video.title = form.title.data
        video.description = '<br>'.join(form.description.data.split('\n'))
        db_sess.commit()
        video_file.save(os.path.join('static/vid', f'{video.id}.mp4'))
        preview_file.save(os.path.join('static/pre', f'{video.id}.jpg'))
        with Image.open(f'static/pre/{video.id}.jpg') as preview_file:
            width, height = preview_file.size
            if width >= height:
                new_width = height * 16 // 9
                delta = (width - new_width) // 2
                preview_file = preview_file.crop((delta, 0, new_width + delta, height))
            else:
                new_height = width * 9 // 16
                delta = (height - new_height) // 2
                preview_file = preview_file.crop((0, delta, width, new_height + delta))
            preview_file.save(f'static/pre/{video.id}.jpg')
        return redirect('/')
    return render_template('edit_video.html', form=form, **params)


@app.route('/delete_video/<int:video_id>')
def delete_video(video_id):
    """
    Удаляет видео если пользователь авторизован и является автором,
    иначе доступ запрещен
    """
    video = db_sess.query(Video).get(video_id)
    if not int(current_user.id) == int(video.author):
        print(f"Current user ID: {current_user.id}, Video author ID: {video.author}")  # Debugging line
        return redirect('/')
    db_sess.delete(video)
    db_sess.commit()
    os.remove(os.path.join('static/vid', f'{video.id}.mp4'))
    os.remove(os.path.join('static/pre', f'{video.id}.jpg'))
    return redirect(f'/user/{current_user.id}')


@app.route('/user/<int:user_id>')
def user(user_id):
    """Возвращает страницу выбранного пользователя с его видео"""
    user = db_sess.query(User).get(user_id)
    if user is None:
        return page_not_found('')
    videos = db_sess.query(Video).filter(Video.author == user_id).all()[::-1]
    subscription = False
    if current_user.is_authenticated:
        subscriptions = json.loads(current_user.subscriptions)
        if user_id in subscriptions:
            subscription = True
    params = {
        'title': f'{user.name} {user.surname}',
        'user': user,
        'videos': [videos[i * 3:i * 3 + 3] for i in range(len(videos) // 3)] +
                  [videos[(len(videos) // 3) * 3:]],
        'subscription': subscription,
        'empty': True if len(videos) == 0 else False,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('user.html', **params)


@app.route('/feed')
def feed():
    """
    Возвращает страницу с лентой видео от людей,
    на которых подписан пользователь.
    Если пользователь не авторизован, доступ запрещен
    """
    if not current_user.is_authenticated:
        return forbidden('')
    subscriptions = json.loads(current_user.subscriptions)
    videos = []
    for i in subscriptions:
        videos += db_sess.query(Video).filter(Video.author == i).all()[::-1][:12]
    new_videos = sorted(videos, key=lambda x: x.datetime)[::-1]
    new_videos = [
        {
            'video': i,
            'author': db_sess.query(User).get(i.author)
        }
        for i in new_videos
    ]
    params = {
        'title': f'Лента',
        'new_videos': [new_videos[i * 3:i * 3 + 3] for i in range(len(new_videos) // 3)] +
                      [new_videos[(len(new_videos) // 3) * 3:]],
        'empty': True if len(new_videos) == 0 else False,
        'subscripted': True if len(subscriptions) != 0 else False,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('feed.html', **params)


@app.route('/favorite')
def favorite():
    """
    Возвращает страницу с любимыми видео пользователя.
    Если пользователь не авторизован, доступ запрещен
    """
    if not current_user.is_authenticated:
        return forbidden('')
    likes = json.loads(current_user.likes)[::-1]
    liked_videos = [
        {
            'video': db_sess.query(Video).get(i),
            'author': db_sess.query(User).get(db_sess.query(Video).get(i).author)
        }
        for i in likes
    ]
    params = {
        'title': f'Любимое',
        'liked_videos': [liked_videos[i * 3:i * 3 + 3] for i in range(len(liked_videos) // 3)] +
                        [liked_videos[(len(liked_videos) // 3) * 3:]],
        'empty': True if len(liked_videos) == 0 else False,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('favorite.html', **params)


@app.route('/people')
def people():
    """
    Возвращает страницу с пользователями, на которых подписан пользователь.
    Если пользователь не авторизован, доступ запрещен
    """
    if not current_user.is_authenticated:
        return forbidden('')
    subscriptions = json.loads(current_user.subscriptions)
    subscripted_users = [
        {
            'user': db_sess.query(User).get(i)
        }
        for i in subscriptions
    ]
    subscripted_users.sort(key=lambda x: x['user'].name + x['user'].surname + x['user'].login)
    params = {
        'title': f'Люди',
        'subscripted_users': subscripted_users,
        'empty': True if len(subscripted_users) == 0 else False,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('people.html', **params)

@app.route('/about')
def about():
    params = {
        'title': f'Про сайт'

    }
    return render_template('about.html', **params)
@app.route('/search')
def search():
    """Возвращает страницу с результатами поиска видео"""
    query = request.args['search']
    videos = db_sess.query(Video).filter(Video.title == query).all()
    params = {
        'title': f'Поиск: {query}',
        'query': query,
        'videos': videos,
        'empty': len(videos) == 0,
        'db_sess': db_sess,
        'User': User,
        'authenticated': current_user.is_authenticated,
        'current_user': current_user
    }
    return render_template('search.html', **params)


db_session.global_init("db/hosting.sql")
db_sess = db_session.create_session()
db_sess.rollback
api.add_resource(UsersResource, '/api/users/<int:user_id>')
api.add_resource(UserListResource, '/api/users')
api.add_resource(VideosResource, '/api/videos/<int:video_id>')
api.add_resource(VideoListResource, '/api/videos')
api.add_resource(LikeResource, '/api/like/<int:video_id>')
api.add_resource(NotLikeResource, '/api/not_like/<int:video_id>')
api.add_resource(FollowResource, '/api/follow/<int:user_id>')
api.add_resource(NotFollowResource, '/api/not_follow/<int:user_id>')

if __name__ == '__main__':
    app.run(debug=True, port=8080, host='0.0.0.0')
This my htmls:
add_video.html:
{% extends "base.html" %}

{% block content %}
    <h2>Добавление видео</h2>
    <form action="" method="post" enctype="multipart/form-data">
        {{ form.hidden_tag() }}
        {% if message %}
            <div class="row mb-3" style="margin-top: 20px">
                <div class="alert alert-danger" role="alert">
                    {{ message }}
                </div>
            </div>
        {% endif %}
        <div class="row mb-3">
            <div class="col-sm-2 col-form-label">
                {{ form.title.label }}
            </div>
            <div class="col-sm-10">
                {{ form.title(class="form-control", type="title") }}
                {% for error in form.title.errors %}
                <div class="alert alert-danger" role="alert">
                    {{ error }}
                </div>
                {% endfor %}
            </div>
        </div>
        <div class="row mb-3">
            <div class="col-sm-2 col-form-label">
                {{ form.description.label }}
            </div>
            <div class="col-sm-10">
                {{ form.description(class="form-control", type="description") }}
                {% for error in form.description.errors %}
                <div class="alert alert-danger" role="alert">
                    {{ error }}
                </div>
                {% endfor %}
            </div>
        </div>
        <div class="row mb-3">
            <div class="col-sm-2 col-form-label">
                {{ form.video.label }}
            </div>
            <div class="col-sm-10">
                {{ form.video(class="form-control", type="file") }}
                {% for error in form.video.errors %}
                <div class="alert alert-danger" role="alert">
                    {{ error }}
                </div>
                {% endfor %}
            </div>
        </div>
        <div class="row mb-3">
            <div class="col-sm-2 col-form-label">
                {{ form.preview.label }}
            </div>
            <div class="col-sm-10">
                {{ form.preview(class="form-control", type="file") }}
                {% for error in form.preview.errors %}
                <div class="alert alert-danger" role="alert">
                    {{ error }}
                </div>
                {% endfor %}
            </div>
        </div>
        <div class="">
            {{ form.submit(type="submit", class="btn btn-primary") }}
        </div>
    </form>
{% endblock %}
user.html:
{% extends "base.html" %}

{% block content %}
    <div class="row justify-content-start">
        <div class="col-sm-auto">
            <h2>
                <img src="{{ url_for('static', filename='avatars/' ~ user.avatar) }}" alt="Avatar" style="width:100px; height:100px; border-radius:50%;">
                {{ user.name }} {{ user.surname }}
                <button onclick="follow()" class="btn btn-outline-danger {% if subscription %} active {% endif %}" type="submit" name="follow" id="follow" {% if not authenticated or current_user.id == user.id %} disabled {% endif %}>
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-plus-fill" viewBox="0 0 16 16">
                        <path d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
                        <path fill-rule="evenodd" d="M13.5 5a.5.5 0 0 1 .5.5V7h1.5a.5.5 0 0 1 0 1H14v1.5a.5.5 0 0 1-1 0V8h-1.5a.5.5 0 0 1 0-1H13V5.5a.5.5 0 0 1 .5-.5z"/>
                    </svg>

                    <span id="followers">{{ user.followers }}</span>
                </button>
                #{{ user.login }}
            </h2>
        </div>
                {% if authenticated and current_user.id == user.id %}
            <div class="col-sm-auto">

            </div>
        {% endif %}
        <div class="col-sm-auto">
            <h2 class="text-secondary">

            </h2>
        </div>
        <div class="col-sm-auto">
            <h2>

            </h2>
        </div>
    </div>
    {% if authenticated and current_user.id == user.id %}
    <div class="row" style="margin-bottom: 10px">
        <div class="col-sm-auto">
            <a href="/add_video" class="btn btn-primary" role="button">Добавить видео</a>
            <a href="{{ url_for('upload_avatar') }}" class="btn btn-secondary">Изменить Аватар</a>
        </div>
    </div>
    {% endif %}
    <div class="row">
        <div class="row">
            <h4>Все видео</h4>
        </div>
        <div class="row">
            {% if empty %}
                {% if authenticated and current_user.id == user.id%}
                    <h5>Вы пока не загрузили ни одного видео, но может вы можете сделать это в любой момент с помощью кнопки "Добавить видео"</h5>
                {% else %}
                    <h5>Пользователь не загрузил ни одного видео</h5>
                {% endif %}
            {% else %}
                {% for row in videos %}
                <div class="row">
                    {% for vid in row %}
                    <div class="col-4">
                        <a href="/video/{{ vid.id }}"><img src="/static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                        <a href="/video/{{ vid.id }}" class="text-decoration-none text-dark">{{ vid.title }}</a>
                    </div>
                    {% endfor %}
                </div>
                {% endfor %}
            {% endif %}
        </div>
    </div>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"> </script>
    <script type=text/javascript>
        function follow() {
            var follow = document.getElementById("follow");
            var unfollow = document.getElementById("unfollow");
            var followers = document.getElementById("followers");
            if ( follow.classList.contains('active') )
            {
                follow.classList.remove("active");
                followers.innerHTML = parseInt(followers.innerText) - 1;
                $.post('/api/not_follow/{{ user.id }}');
            }
            else
            {
                follow.classList.add("active");
                followers.innerHTML = parseInt(followers.innerText) + 1;
                $.post('/api/follow/{{ user.id }}');
                if ( unfollow.classList.contains('active') )
                {
                    unfollow.classList.remove("active");
                    followers.innerHTML = parseInt(followers.innerText) + 1;
                }
            }
        }
    </script>
{% endblock %}
video.html:
{% extends "base.html" %}

{% block content %}
    <div class="row">
        <div class="col-9">
            <div class="row">
                <div class="col">
                <div class="video-container paused" data-volume-level="high">
    <img class="thumbnail-img">
    <div class="video-controls-container">
      <div class="timeline-container">
        <div class="timeline">
          <img class="preview-img">
          <div class="thumb-indicator"></div>
        </div>
      </div>
      <div class="controls">
        <button class="play-pause-btn">
          <svg class="play-icon" viewBox="0 0 24 24">
            <path fill="currentColor" d="M8,5.14V19.14L19,12.14L8,5.14Z" />
          </svg>
          <svg class="pause-icon" viewBox="0 0 24 24">
            <path fill="currentColor" d="M14,19H18V5H14M6,19H10V5H6V19Z" />
          </svg>
        </button>
        <div class="volume-container">
          <button class="mute-btn">
            <svg class="volume-high-icon" viewBox="0 0 24 24">
              <path fill="currentColor" d="M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.84 14,18.7V20.77C18,19.86 21,16.28 21,12C21,7.72 18,4.14 14,3.23M16.5,12C16.5,10.23 15.5,8.71 14,7.97V16C15.5,15.29 16.5,13.76 16.5,12M3,9V15H7L12,20V4L7,9H3Z" />
            </svg>
            <svg class="volume-low-icon" viewBox="0 0 24 24">
              <path fill="currentColor" d="M5,9V15H9L14,20V4L9,9M18.5,12C18.5,10.23 17.5,8.71 16,7.97V16C17.5,15.29 18.5,13.76 18.5,12Z" />
            </svg>
            <svg class="volume-muted-icon" viewBox="0 0 24 24">
              <path fill="currentColor" d="M12,4L9.91,6.09L12,8.18M4.27,3L3,4.27L7.73,9H3V15H7L12,20V13.27L16.25,17.53C15.58,18.04 14.83,18.46 14,18.7V20.77C15.38,20.45 16.63,19.82 17.68,18.96L19.73,21L21,19.73L12,10.73M19,12C19,12.94 18.8,13.82 18.46,14.64L19.97,16.15C20.62,14.91 21,13.5 21,12C21,7.72 18,4.14 14,3.23V5.29C16.89,6.15 19,8.83 19,12M16.5,12C16.5,10.23 15.5,8.71 14,7.97V10.18L16.45,12.63C16.5,12.43 16.5,12.21 16.5,12Z" />
            </svg>
          </button>
          <input class="volume-slider" type="range" min="0" max="1" step="any" value="1">
        </div>
        <div class="duration-container">
          <div class="current-time">0:00</div>
          /
          <div class="total-time"></div>
        </div>
        <button class="captions-btn">
          <svg viewBox="0 0 24 24">
            <path fill="currentColor" d="M18,11H16.5V10.5H14.5V13.5H16.5V13H18V14A1,1 0 0,1 17,15H14A1,1 0 0,1 13,14V10A1,1 0 0,1 14,9H17A1,1 0 0,1 18,10M11,11H9.5V10.5H7.5V13.5H9.5V13H11V14A1,1 0 0,1 10,15H7A1,1 0 0,1 6,14V10A1,1 0 0,1 7,9H10A1,1 0 0,1 11,10M19,4H5C3.89,4 3,4.89 3,6V18A2,2 0 0,0 5,20H19A2,2 0 0,0 21,18V6C21,4.89 20.1,4 19,4Z" />
          </svg>
        </button>
        <button class="speed-btn wide-btn">
          1x
        </button>
        <button class="mini-player-btn">
          <svg viewBox="0 0 24 24">
            <path fill="currentColor" d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14zm-10-7h9v6h-9z"/>
          </svg>
        </button>
        <button class="theater-btn">
          <svg class="tall" viewBox="0 0 24 24">
            <path fill="currentColor" d="M19 6H5c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H5V8h14v8z"/>
          </svg>
          <svg class="wide" viewBox="0 0 24 24">
            <path fill="currentColor" d="M19 7H5c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H5V9h14v6z"/>
          </svg>
        </button>
        <button class="full-screen-btn">
          <svg class="open" viewBox="0 0 24 24">
            <path fill="currentColor" d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>
          </svg>
          <svg class="close" viewBox="0 0 24 24">
            <path fill="currentColor" d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>
          </svg>
        </button>
      </div>
    </div>
    <video width="140%" autoplay src="{{ video_src }}">
      <track kind="captions" srclang="en" src="assets/subtitles.vtt">
    </video>
  </div>
                </div>
            </div>
            {% if authenticated and current_user.id|to_int == current_video.author|to_int or current_user.id == 1 %}
            <div style="margin-bottom: 10px">
                <a href="/edit_video/{{ current_video.id }}" class="btn btn-warning" role="button">Изменить видео</a>
                <a href="/delete_video/{{ current_video.id }}" class="btn btn-danger" role="button">Удалить видео</a>
            </div>
            {% endif %}
            <div class="row">
                <div class="col-auto">
                    <h3>
                        {{ current_video.title }}
                    </h3>
                </div>
                <div class="col-auto">
                    <button onclick="like()" class="btn btn-outline-danger btn-sm {% if like %} active {% endif %}" type="submit" name="like" id="like" {% if not authenticated or current_user.id == current_video.author %} disabled {% endif %}>
                        <svg xmlns="http://www.w3.org/2000/svg" height="16px" viewBox="0 -960 960 960" width="16px" fill="#5f6368"><path d="M840-640q32 0 56 24t24 56v80q0 7-2 15t-4 15L794-168q-9 20-30 34t-44 14H280v-520l240-238q15-15 35.5-17.5T595-888q19 10 28 28t4 37l-45 183h258Zm-480 34v406h360l120-280v-80H480l54-220-174 174ZM160-120q-33 0-56.5-23.5T80-200v-360q0-33 23.5-56.5T160-640h120v80H160v360h120v80H160Zm200-80v-406 406Z"></path></svg>
                        <span id="likes">{{ current_video.likes }}</span>
                    </button>
                </div>
            </div>
            <div class="row">
                <div class="col-auto">
                    <h4>
                    <img src="{{ avatar_url }}" alt="Avatar" class="img-fluid rounded-circle m-2" style="width:80px; height:80px;">
                        <a href="/user/{{ author.id }}" class="text-decoration-none text-dark">{{ author.name }} {{ author.surname }}</a>
                    </h4>
                </div>
                <div class="col-auto">
                    <button onclick="follow()" class="btn btn-outline-danger btn-sm {% if subscription %} active {% endif %}" type="submit" name="follow" id="follow" {% if not authenticated or current_user.id == current_video.author %} disabled {% endif %}>
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-plus-fill" viewBox="0 0 16 16">
                            <path d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
                            <path fill-rule="evenodd" d="M13.5 5a.5.5 0 0 1 .5.5V7h1.5a.5.5 0 0 1 0 1H14v1.5a.5.5 0 0 1-1 0V8h-1.5a.5.5 0 0 1 0-1H13V5.5a.5.5 0 0 1 .5-.5z"/>
                        </svg>
                        <span id="followers">{{ author.followers }}</span>
                    </button>
                </div>
            </div>



            <div class="row" style="margin-top: 10px">
                <div class="col">
                    {% autoescape false %}
                    <p style="color: #808080">{{ current_video.description }}</p>
                    {% endautoescape %}
                </div>
            </div>
            <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
            <script type=text/javascript>
                function follow() {
                    var follow = document.getElementById("follow");
                    var unfollow = document.getElementById("unfollow");
                    var followers = document.getElementById("followers");
                    if ( follow.classList.contains('active') )
                    {
                        follow.classList.remove("active");
                        followers.innerHTML = parseInt(followers.innerText) - 1;
                        $.post('/api/not_follow/{{ current_video.author }}');
                    }
                    else
                    {
                        follow.classList.add("active");
                        followers.innerHTML = parseInt(followers.innerText) + 1;
                        $.post('/api/follow/{{ current_video.author }}');
                        if ( unfollow.classList.contains('active') )
                        {
                            unfollow.classList.remove("active");
                            followers.innerHTML = parseInt(followers.innerText) + 1;
                        }
                    }
                }

                function like() {
                    var like = document.getElementById("like");
                    var dislike = document.getElementById("dislike");
                    var likes = document.getElementById("likes");
                    if ( like.classList.contains('active') )
                    {
                        like.classList.remove("active");
                        likes.innerHTML = parseInt(likes.innerText) - 1;
                        $.post('/api/not_like/{{ current_video.id }}');
                    }
                    else
                    {
                        like.classList.add("active");
                        likes.innerHTML = parseInt(likes.innerText) + 1;
                        $.post('/api/like/{{ current_video.id }}');
                        if ( dislike.classList.contains('active') )
                        {
                            dislike.classList.remove("active");
                            likes.innerHTML = parseInt(likes.innerText) + 1;
                        }
                    }
                }





const playPauseBtn = document.querySelector(".play-pause-btn")
const theaterBtn = document.querySelector(".theater-btn")
const fullScreenBtn = document.querySelector(".full-screen-btn")
const miniPlayerBtn = document.querySelector(".mini-player-btn")
const muteBtn = document.querySelector(".mute-btn")
const captionsBtn = document.querySelector(".captions-btn")
const speedBtn = document.querySelector(".speed-btn")
const currentTimeElem = document.querySelector(".current-time")
const totalTimeElem = document.querySelector(".total-time")
const previewImg = document.querySelector(".preview-img")
const thumbnailImg = document.querySelector(".thumbnail-img")
const volumeSlider = document.querySelector(".volume-slider")
const videoContainer = document.querySelector(".video-container")
const timelineContainer = document.querySelector(".timeline-container")
const video = document.querySelector("video")

document.addEventListener("keydown", e => {
  const tagName = document.activeElement.tagName.toLowerCase()

  if (tagName === "input") return

  switch (e.key.toLowerCase()) {
    case " ":
      if (tagName === "button") return
    case "k":
      togglePlay()
      break
    case "f":
      toggleFullScreenMode()
      break
    case "t":
      toggleTheaterMode()
      break
    case "i":
      toggleMiniPlayerMode()
      break
    case "m":
      toggleMute()
      break
    case "arrowleft":
    case "j":
      skip(-5)
      break
    case "arrowright":
    case "l":
      skip(5)
      break
    case "c":
      toggleCaptions()
      break
  }
})

// Timeline
timelineContainer.addEventListener("mousemove", handleTimelineUpdate)
timelineContainer.addEventListener("mousedown", toggleScrubbing)
document.addEventListener("mouseup", e => {
  if (isScrubbing) toggleScrubbing(e)
})
document.addEventListener("mousemove", e => {
  if (isScrubbing) handleTimelineUpdate(e)
})

let isScrubbing = false
let wasPaused = false
function toggleScrubbing(e) {
  const rect = timelineContainer.getBoundingClientRect()
  const percent = Math.min(Math.max(0, e.x - rect.x), rect.width) / rect.width
  isScrubbing = (e.buttons & 1) === 1
  videoContainer.classList.toggle("scrubbing", isScrubbing)
  if (isScrubbing) {
    wasPaused = video.paused
    video.pause()
  } else {
    video.currentTime = percent * video.duration
    if (!wasPaused) video.play()
  }

  handleTimelineUpdate(e)
}

function handleTimelineUpdate(e) {
  const rect = timelineContainer.getBoundingClientRect()
  const percent = Math.min(Math.max(0, e.x - rect.x), rect.width) / rect.width
  const previewImgNumber = Math.max(
    1,
    Math.floor((percent * video.duration) / 10)
  )
  const previewImgSrc = "/static/pre/{{ current_video.id }}.jpg"
  previewImg.src = previewImgSrc
  timelineContainer.style.setProperty("--preview-position", percent)

  if (isScrubbing) {
    e.preventDefault()
    thumbnailImg.src = previewImgSrc
    timelineContainer.style.setProperty("--progress-position", percent)
  }
}

// Playback Speed
speedBtn.addEventListener("click", changePlaybackSpeed)

function changePlaybackSpeed() {
  let newPlaybackRate = video.playbackRate + 0.25
  if (newPlaybackRate > 3) newPlaybackRate = 0.25
  video.playbackRate = newPlaybackRate
  speedBtn.textContent = `${newPlaybackRate}x`
}

// Captions
const captions = video.textTracks[0]
captions.mode = "hidden"

captionsBtn.addEventListener("click", toggleCaptions)

function toggleCaptions() {
  const isHidden = captions.mode === "hidden"
  captions.mode = isHidden ? "showing" : "hidden"
  videoContainer.classList.toggle("captions", isHidden)
}

// Duration
video.addEventListener("loadeddata", () => {
  totalTimeElem.textContent = formatDuration(video.duration)
})

video.addEventListener("timeupdate", () => {
  currentTimeElem.textContent = formatDuration(video.currentTime)
  const percent = video.currentTime / video.duration
  timelineContainer.style.setProperty("--progress-position", percent)
})

const leadingZeroFormatter = new Intl.NumberFormat(undefined, {
  minimumIntegerDigits: 2,
})
function formatDuration(time) {
  const seconds = Math.floor(time % 60)
  const minutes = Math.floor(time / 60) % 60
  const hours = Math.floor(time / 3600)
  if (hours === 0) {
    return `${minutes}:${leadingZeroFormatter.format(seconds)}`
  } else {
    return `${hours}:${leadingZeroFormatter.format(
      minutes
    )}:${leadingZeroFormatter.format(seconds)}`
  }
}

function skip(duration) {
  video.currentTime += duration
}

// Volume
muteBtn.addEventListener("click", toggleMute)
volumeSlider.addEventListener("input", e => {
  video.volume = e.target.value
  video.muted = e.target.value === 0
})

function toggleMute() {
  video.muted = !video.muted
}

video.addEventListener("volumechange", () => {
  volumeSlider.value = video.volume
  let volumeLevel
  if (video.muted || video.volume === 0) {
    volumeSlider.value = 0
    volumeLevel = "muted"
  } else if (video.volume >= 0.5) {
    volumeLevel = "high"
  } else {
    volumeLevel = "low"
  }

  videoContainer.dataset.volumeLevel = volumeLevel
})

// View Modes
theaterBtn.addEventListener("click", toggleTheaterMode)
fullScreenBtn.addEventListener("click", toggleFullScreenMode)
miniPlayerBtn.addEventListener("click", toggleMiniPlayerMode)

function toggleTheaterMode() {
  videoContainer.classList.toggle("theater")
}

function toggleFullScreenMode() {
  if (document.fullscreenElement == null) {
    videoContainer.requestFullscreen()
  } else {
    document.exitFullscreen()
  }
}

function toggleMiniPlayerMode() {
  if (videoContainer.classList.contains("mini-player")) {
    document.exitPictureInPicture()
  } else {
    video.requestPictureInPicture()
  }
}

document.addEventListener("fullscreenchange", () => {
  videoContainer.classList.toggle("full-screen", document.fullscreenElement)
})

video.addEventListener("enterpictureinpicture", () => {
  videoContainer.classList.add("mini-player")
})

video.addEventListener("leavepictureinpicture", () => {
  videoContainer.classList.remove("mini-player")
})

// Play/Pause
playPauseBtn.addEventListener("click", togglePlay)
video.addEventListener("click", togglePlay)

function togglePlay() {
  video.paused ? video.play() : video.pause()
}

video.addEventListener("play", () => {
  videoContainer.classList.remove("paused")
})

video.addEventListener("pause", () => {
  videoContainer.classList.add("paused")
})
            </script>
        </div>
        <style>
        *, *::before, *::after {
  box-sizing: border-box;
}

body {
  margin: 0;
}

.video-container {
  position: relative;
  width: 90%;
  max-width: 1000px;
  display: flex;
  justify-content: center;
  margin-inline: auto;
  background-color: black;
}

.video-container.theater,
.video-container.full-screen {
  max-width: initial;
  width: 100%;
}

.video-container.theater {
  max-height: 90vh;
}

.video-container.full-screen {
  max-height: 100vh;
}

video {
  width: 100%;
}

.video-controls-container {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  color: white;
  z-index: 100;
  opacity: 0;
  transition: opacity 150ms ease-in-out;
}

.video-controls-container::before {
  content: "";
  position: absolute;
  bottom: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, .75), transparent);
  width: 100%;
  aspect-ratio: 6 / 1;
  z-index: -1;
  pointer-events: none;
}

.video-container:hover .video-controls-container,
.video-container:focus-within .video-controls-container,
.video-container.paused .video-controls-container {
  opacity: 1;
}

.video-controls-container .controls {
  display: flex;
  gap: .5rem;
  padding: .25rem;
  align-items: center;
}

.video-controls-container .controls button {
  background: none;
  border: none;
  color: inherit;
  padding: 0;
  height: 30px;
  width: 30px;
  font-size: 1.1rem;
  cursor: pointer;
  opacity: .85;
  transition: opacity 150ms ease-in-out;
}

.video-controls-container .controls button:hover {
  opacity: 1;
}

.video-container.paused .pause-icon {
  display: none;
}

.video-container:not(.paused) .play-icon {
  display: none;
}

.video-container.theater .tall {
  display: none;
}

.video-container:not(.theater) .wide {
  display: none;
}

.video-container.full-screen .open {
  display: none;
}

.video-container:not(.full-screen) .close {
  display: none;
}

.volume-high-icon,
.volume-low-icon,
.volume-muted-icon {
  display: none;
}

.video-container[data-volume-level="high"] .volume-high-icon {
  display: block;
}

.video-container[data-volume-level="low"] .volume-low-icon {
  display: block;
}

.video-container[data-volume-level="muted"] .volume-muted-icon {
  display: block;
}

.volume-container {
  display: flex;
  align-items: center;
}

.volume-slider {
  width: 0;
  transform-origin: left;
  transform: scaleX(0);
  transition: width 150ms ease-in-out, transform 150ms ease-in-out;
  background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet, red);
}

.volume-container:hover .volume-slider,
.volume-slider:focus-within {
  width: 100px;
  transform: scaleX(1);
}

.duration-container {
  display: flex;
  align-items: center;
  gap: .25rem;
  flex-grow: 1;
}

.video-container.captions .captions-btn {
  border-bottom: 3px solid red;
}

.video-controls-container .controls button.wide-btn {
  width: 50px;
}

.timeline-container {
  height: 7px;
  margin-inline: .5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
}

.timeline {
  background-color: rgba(100, 100, 100, .5);
  height: 3px;
  width: 100%;
  position: relative
}

.timeline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: calc(100% - var(--preview-position) * 100%);
  background-color: rgb(150, 150, 150);
  display: none;
}

.timeline::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: calc(100% - var(--progress-position) * 100%);
  background: linear-gradient(45deg, red, orange, yellow, green, blue, indigo, violet, red);
}

.timeline .thumb-indicator {
  --scale: 0;
  position: absolute;
  transform: translateX(-50%) scale(var(--scale));
  height: 200%;
  top: -50%;
  left: calc(var(--progress-position) * 100%);
  background-color: red;
  border-radius: 50%;
  transition: transform 150ms ease-in-out;
  aspect-ratio: 1 / 1;
}

.timeline .preview-img {
  position: absolute;
  height: 80px;
  aspect-ratio: 16 / 9;
  top: -1rem;
  transform: translate(-50%, -100%);
  left: calc(var(--preview-position) * 100%);
  border-radius: .25rem;
  border: 2px solid white;
  display: none;
}

.thumbnail-img {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  display: none;
}

.video-container.scrubbing .thumbnail-img {
  display: block;
}

.video-container.scrubbing .preview-img,
.timeline-container:hover .preview-img {
  display: block;
}

.video-container.scrubbing .timeline::before,
.timeline-container:hover .timeline::before {
  display: block;
}

.video-container.scrubbing .thumb-indicator,
.timeline-container:hover .thumb-indicator {
  --scale: 1;
}

.video-container.scrubbing .timeline,
.timeline-container:hover .timeline {
  height: 100%;
}
        </style>
        <div class="col-3">
            {% for vid in last_videos %}
            <div class="row">
                <a href="/video/{{ vid.id }}"><img src="/static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                <p><a class="text-decoration-none text-dark" href="/video/{{ vid.id }}">{{ vid.title }}</a> - <a class="text-decoration-none text-dark" href="/user/{{ db_sess.query(User).filter(User.id == vid.author).first().id }}">{{ db_sess.query(User).filter(User.id == vid.author).first().name }} {{ db_sess.query(User).filter(User.id == vid.author).first().surname }}</a></p>
            </div>
            {% endfor %}
        </div>
    </div>
{% endblock %}
base.html:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link
                href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css"
                rel="stylesheet"
                integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6"
                crossorigin="anonymous">
        <style type="text/css">

        </style>
        <title>{{ title }}</title>
    </head>
    <body>
        <nav class="navbar sticky-top navbar-expand-lg navbar-light bg-light">
            <div class="container-fluid">
                <a class="navbar-brand mb-0 h1" href="/">

                    <img src="/static/img/vhs.png" alt="" width="201 height="35">
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                        <li class="nav-item">
                            <a class="nav-link" href="/">Главная</a>
                        </li>
                        {% if authenticated %}
                            <li class="nav-item">
                                <a class="nav-link" href="/feed">Лента</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/favorite">Избранное</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/people">Пользователи</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/user/{{ current_user.id }}">Мои видео</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/logout">Выйти</a>

                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/about">Про сайт</a>
                            </li>
                        {% else %}
                            <li class="nav-item">
                                <a class="nav-link" href="/login">Войти</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/register">Зарегаться</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link" href="/about">Про сайт</a>
                            </li>
                        {% endif %}
                    </ul>

                    <form class="d-flex" action="/search">
                        <input class="form-control me-2" type="search" name="search" placeholder="Поиск" aria-label="Search">
                        <button class="btn btn-outline-success" type="submit">Найти</button>
                    </form>
                </div>
            </div>
        </nav>
        <div class="container" style="margin-top: 20px">
            {% block content %}{% endblock %}
        </div>
        <script
                src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
                integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
                crossorigin="anonymous">
        </script>
        <style>
        div {
            backdrop-filter: blur(10px);
        }
        </style>
    </body>
</html>
index.html:
{% extends "base.html" %}

{% block content %}
    <div class="row">
        <div class="row">
            <h4>Новинки</h4>
        </div>
        <div class="row">
            {% for vid in last_videos %}
            <div class="col-4">
                <a href="/video/{{ vid.id }}"><img src="static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                <p><a class="text-decoration-none text-dark" href="/video/{{ vid.id }}">{{ vid.title }}</a> - <a class="text-decoration-none text-dark" href="/user/{{ db_sess.query(User).filter(User.id == vid.author).first().id }}">{{ db_sess.query(User).filter(User.id == vid.author).first().name }} {{ db_sess.query(User).filter(User.id == vid.author).first().surname }}</a></p>
            </div>
            {% endfor %}
        </div>
    </div>
    <div class="row">
        <div class="row">
            <h4>Лучшее</h4>
        </div>
        <div class="row">
            {% for vid in best_videos %}
            <div class="col-4">
                <a href="/video/{{ vid.id }}"><img src="static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                <p><a class="text-decoration-none text-dark" href="/video/{{ vid.id }}">{{ vid.title }}</a> - <a class="text-decoration-none text-dark" href="/user/{{ db_sess.query(User).filter(User.id == vid.author).first().id }}">{{ db_sess.query(User).filter(User.id == vid.author).first().name }} {{ db_sess.query(User).filter(User.id == vid.author).first().surname }}</a></p>
            </div>
            {% endfor %}
        </div>
    </div>
    <div class="row">
        <div class="row">
            <h4>Недооцененное</h4>
        </div>
        <div class="row">
            {% for vid in underrated_videos %}
            <div class="col-4">
                <a href="/video/{{ vid.id }}"><img src="static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                <p><a class="text-decoration-none text-dark" href="/video/{{ vid.id }}">{{ vid.title }}</a> - <a class="text-decoration-none text-dark" href="/user/{{ db_sess.query(User).filter(User.id == vid.author).first().id }}">{{ db_sess.query(User).filter(User.id == vid.author).first().name }} {{ db_sess.query(User).filter(User.id == vid.author).first().surname }}</a></p>
            </div>
            {% endfor %}
        </div>

        <div class="row">
            <h4>Все видео</h4>
        </div>
        <div class="row">
            {% for vid in all_videos %}
            <div class="col-4">
                <a href="/video/{{ vid.id }}"><img src="static/pre/{{ vid.id }}.jpg" style="width: 100%"></a>
                <p><a class="text-decoration-none text-dark" href="/video/{{ vid.id }}">{{ vid.title }}</a> - <a class="text-decoration-none text-dark" href="/user/{{ db_sess.query(User).filter(User.id == vid.author).first().id }}">{{ db_sess.query(User).filter(User.id == vid.author).first().name }} {{ db_sess.query(User).filter(User.id == vid.author).first().surname }}</a></p>
            </div>
            {% endfor %}
        </div>

    </div>
{% endblock %}
data folder:
videos.py:
import sqlalchemy
from .db_session import SqlAlchemyBase
from sqlalchemy_serializer import SerializerMixin
from datetime import datetime


class Video(SqlAlchemyBase, SerializerMixin):
    """Определяет таблицу с видео в базе данных"""
    __tablename__ = 'videos'

    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, unique=True, autoincrement=True, nullable=False)
    title = sqlalchemy.Column(sqlalchemy.String, nullable=False)
    author = sqlalchemy.Column(sqlalchemy.String, sqlalchemy.ForeignKey("users.id"), nullable=False)
    description = sqlalchemy.Column(sqlalchemy.String, nullable=False, default='')
    likes = sqlalchemy.Column(sqlalchemy.Integer, nullable=False, default=0)
    datetime = sqlalchemy.Column(sqlalchemy.DateTime, nullable=False, default=datetime.utcnow)
users.py:
# data/users.py
from sqlalchemy import Column, Integer, String, Text
from flask_login import UserMixin
from .db_session import SqlAlchemyBase

class User(UserMixin, SqlAlchemyBase):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    login = Column(String, unique=True, nullable=True)
    password = Column(String, nullable=True)
    name = Column(String, nullable=True)
    surname = Column(String, nullable=True)
    likes = Column(Text, nullable=True, default='[]')  # Users' liked videos
    subscriptions = Column(Text, nullable=True, default='[]')  # Users this user subscribes to
    followers = Column(Integer, nullable=True, default=0)  # Number of followers
    avatar = Column(String, nullable=True, default='default.png')
    # User avatar
users_arg_parser.py:
from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('login', required=True, type=str)
parser.add_argument('password', required=True, type=str)
parser.add_argument('name', required=True, type=str)
parser.add_argument('surname', required=True, type=str)
static folder:
/fonts/
/pre/
/vid/
/img/
/avatars/
User with id 1- admin
Main prompt:'add channel name editing(only if it's your channel or if it's user with id 1), add fully deleting channel with all its videos, (availiable for the owner of the channel or user with id 1),channel description editing and adding (only for owner of the channel) '