Вот мой код:
```py
# app.py
import shutil
import sqlite3
import zipfile
from io import BytesIO

from flask import Flask, request, jsonify, send_from_directory, render_template, send_file
from flask_cors import CORS
from database import Database
import os
import uuid
from werkzeug.utils import secure_filename

app = Flask(__name__, static_folder='static', template_folder='templates')
CORS(app)

db = Database()

# Убедимся, что папка для хранения треков существует
TRACKS_DIR = os.path.join(app.static_folder, 'tracks')
os.makedirs(TRACKS_DIR, exist_ok=True)

# Ограничение для допустимых расширений файлов
ALLOWED_EXTENSIONS = {'mp3', 'wav', 'aac', 'flac', 'ogg', 'm4a'}

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# Ограничение размера файла, например, до 100MB
MAX_CONTENT_LENGTH = 100 * 1024 * 1024  # 100MB
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH

# Главная страница
@app.route('/')
def index():
    return render_template('index.html')

# Обслуживание статических файлов
@app.route('/static/<path:path>')
def send_static_files(path):
    print(f"pathpathpathpathpath =  {path}")
    return send_from_directory('static', path)

# 1. Получение всех треков (с пагинацией)
@app.route('/tracks', methods=['GET'])
def get_tracks():
    page = request.args.get('page', 1, type=int)
    per_page = 1000
    name = request.args.get('name', type=str)

    if name:
        tracks, total = db.search_tracks_paginated(
            name=name,
            page=page,
            per_page=per_page
        )
    else:
        tracks, total = db.get_tracks(page, per_page)

    return jsonify({'tracks': tracks, 'total': total})

# 2. Поиск треков
@app.route('/tracks/search', methods=['GET'])
def search_tracks():
    description = request.args.get('description', '', type=str)
    tags = request.args.getlist('tags')
    tracks = db.search_tracks(description, tags)
    return jsonify({'tracks': tracks})

# 3. Добавление нового трека с загрузкой файла
@app.route('/tracks', methods=['POST'])
def add_track():
    # Получение оригинальной ссылки, если она существует
    original_url = request.form.get('url')  # Сделали необязательным

    # Проверяем наличие файла в запросе
    if 'file' not in request.files:
        return jsonify({'error': 'Файл трека обязателен.'}), 400

    file = request.files['file']

    # Получаем другие поля формы
    name = request.form.get('name')
    description = request.form.get('description')
    tags = request.form.getlist('tags')  # Ожидаем, что теги передаются как список

    # Проверяем обязательные поля
    if not name:
        return jsonify({'error': 'Название трека обязательно.'}), 400

    if file.filename == '':
        return jsonify({'error': 'Выберите файл для загрузки.'}), 400

    if file and allowed_file(file.filename):
        # Обезопасим имя файла
        filename = secure_filename(file.filename)
        # Генерируем уникальное имя файла
        unique_filename = f"{uuid.uuid4()}_{filename}"
        file_path = os.path.join(TRACKS_DIR, unique_filename)
        file.save(file_path)

        # URL для доступа к файлу
        local_url = f"/tracks/{unique_filename}"

        # Добавляем трек в базу данных
        track_id = db.add_track(name, description, local_url, original_url, tags)

        return jsonify({'message': 'Трек успешно добавлен.', 'track_id': track_id}), 201
    else:
        return jsonify({'error': 'Недопустимый тип файла. Поддерживаемые форматы: mp3, wav, aac, flac, ogg, m4a.'}), 400

# 4. Удаление трека
@app.route('/tracks/<int:track_id>', methods=['DELETE'])
def delete_track(track_id):
    # Получаем трек по ID
    track = db.get_track_by_id(track_id)
    if not track:
        return jsonify({'error': 'Трек не найден.'}), 404

    # Удаляем трек из базы данных
    db.delete_track(track_id)

    # Удаляем локальный файл
    file_path = os.path.join(app.root_path, track['url'].lstrip('/'))
    if os.path.exists(file_path):
        try:
            os.remove(file_path)
        except Exception as e:
            # Можно логировать ошибку или обработать иначе
            pass

    return jsonify({'message': 'Трек успешно удален.'}), 200

@app.route('/get_db')
def download_db():
    try:
        memory_file = BytesIO()
        with zipfile.ZipFile(memory_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # Добавляем базу данных в архив
            zipf.write(db.db_path, arcname='tracks.db')

            # Добавляем файлы треков в архив
            for root, _, files in os.walk(TRACKS_DIR):
                for file in files:
                    zipf.write(os.path.join(root, file), arcname=os.path.relpath(os.path.join(root, file), app.static_folder))

        memory_file.seek(0)

        return send_file(memory_file, as_attachment=True, download_name="tracks_backup.zip", mimetype="application/zip")

    except Exception as e:
        print(f"Error creating backup: {e}")
        return jsonify({'error': 'Ошибка при создании бэкапа.'}), 500



@app.route('/set_db', methods=['POST'])
def upload_db():
    if 'db_file' not in request.files:
        return jsonify({'error': 'Файл базы данных не найден.'}), 400

    file = request.files['db_file']
    if file.filename == '':
        return jsonify({'error': 'Файл не выбран.'}), 400

    temp_dir = os.path.join(app.instance_path, f"temp_{uuid.uuid4()}") # instance_path более безопасный
    os.makedirs(temp_dir, exist_ok=True)

    temp_db_path = None

    try:
        file.save(os.path.join(temp_dir, "temp_backup.zip"))


        with zipfile.ZipFile(os.path.join(temp_dir, "temp_backup.zip"), 'r') as zip_ref:
            zip_ref.extractall(temp_dir)

        temp_db_path = os.path.join(temp_dir, 'tracks.db')

        # Подключаемся к временной базе данных
        temp_conn = sqlite3.connect(temp_db_path)
        temp_cursor = temp_conn.cursor()

        def get_tags_from_temp_db(temp_cursor, track_name):
            temp_cursor.execute('''
                SELECT t.name, g.name
                FROM tracks AS t
                INNER JOIN track_tags AS tt ON t.id = tt.track_id
                INNER JOIN tags AS g ON tt.tag_id = g.id
                WHERE t.name = ?
            ''', (track_name,))
            tags = [tag[1] for tag in temp_cursor.fetchall() if tag[0] == track_name]
            return tags


        temp_cursor.execute("SELECT name, description, url, original_url FROM tracks")
        tracks = temp_cursor.fetchall()


        # Перемещаем треки в static/tracks
        temp_tracks_dir = os.path.join(temp_dir, 'tracks')
        for filename in os.listdir(temp_tracks_dir):
            shutil.move(os.path.join(temp_tracks_dir, filename), TRACKS_DIR)


        for track in tracks:
            # обновляем url, чтобы он указывал на правильное место
            track_url = track[2] # url из временной БД
            track_filename = os.path.basename(track_url.lstrip('/tracks/')) # достаем имя файла из url
            new_track_url = f'/tracks/{track_filename}' #  формируем новый url
            new_track_id = db.add_track(track[0], track[1], new_track_url, track[3], []) # используем новый url
            tags = get_tags_from_temp_db(temp_cursor, track[0])
            if tags:
                db.add_tags_to_track(new_track_id, tags)

        temp_conn.close()

        return jsonify({'message': 'Данные из базы данных успешно загружены.'}), 200

    except sqlite3.Error as e:
        return jsonify({'error': f'Ошибка SQLite: {e}'}), 400 #  более информативное сообщение
    except Exception as e:
        import traceback
        print(traceback.format_exc())
        return jsonify({'error': f'Ошибка при загрузке данных: {e}'}), 500
    finally:
        #  Удалить временную директорию и все ее содержимое
        if temp_dir:
            try:
               shutil.rmtree(temp_dir)
            except OSError as e:
                print ("Error: %s - %s." % (e.filename, e.strerror))
# Обработка ошибки превышения размера файла
@app.errorhandler(413)
def request_entity_too_large(error):
    return jsonify({'error': 'Файл слишком большой. Максимальный размер: 100MB.'}), 413

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=6390)
```

Вот код js:
```js
// static/app.js

$(document).ready(function () {
    $(".litmusic-text").css("transform", "scale(1.5)");

    setTimeout(function () {
        $(".intro-container").css("pointer-events", "none");
        $(".intro-container").animate({opacity: 0}, 500, function () {
            $(this).remove();
        });
    }, 1000); // Задержка, чтобы анимация transform завершилась

    const $tracksContainer = $('#tracks-container');
    const $addTrackButton = $('#add-track-button');
    const $addTrackDialog = $('#add-track-dialog');
    const $closeAddDialog = $('#close-add-dialog');
    const $addTrackForm = $('#add-track-form');
    const $tagsContainer = $('#tags-container');
    const $addTagButton = $('#add-tag-button');
    const $audioPlayer = $('#audio-player');
    const $audioControl = $('#audio-control');
    const $trackTitle = $('#track-title');
    const $togglePlayerButton = $('#toggle-player-button');
    const $descriptionDialog = $('#description-dialog');
    const $closeDescriptionDialog = $('#close-description-dialog');
    const $descriptionTitle = $('#description-title');
    const $descriptionText = $('#description-text');
    const $searchForm = $('#search-form');
    const $clearSearchButton = $('#clear-search');
    const $paginationControls = $('#pagination-controls');
    const $fileDropArea = $('#file-drop-area');
    const $trackFileInput = $('#track-file');
    const $selectedFileInfo = $('#selected-file-info');
    const $selectedFileName = $('#selected-file-name');
    const $removeSelectedFile = $('#remove-selected-file');
    const $globalOverlay = $('#global-overlay');

    let currentPage = 1;
    const perPage = 10;
    let totalTracks = 0;
    let currentSearch = {
        name: '',
        description: '',
        tags: []
    };
    const animationSpeed = 300; // миллисекунд

    // Переменные для отслеживания текущего трека
    let currentTrackId = null;
    let $currentPlayButton = null;

    // Глобальная переменная для хранения всех треков
    let allTracks = [];

    // --- Функции ---
    function loadTracks(page = 1, search = {}) {
        currentPage = page;
        let url = `/tracks?page=${page}`;
        if (search.name) {
            url += `&name=${encodeURIComponent(search.name)}`;
        }
        if (search.description) {
            url += `&description=${encodeURIComponent(search.description)}`;
        }
        if (search.tags && search.tags.length > 0) {
            search.tags.forEach(tag => {
                url += `&tags=${encodeURIComponent(tag)}`;
            });
        }

        $.getJSON(url, function (data) {
            $tracksContainer.empty();
            totalTracks = data.total;
            allTracks = data.tracks; // Сохраняем загруженные треки
            if (data.tracks.length === 0) {
                $tracksContainer.append('<p>Треки не найдены.</p>');
            } else {
                $.each(data.tracks, function (index, track) {
                    const $trackTile = $('<div class="track-tile"></div>');
                    const $topDiv = $('<div class="top-div"></div>');
                    const $buttons = $('<div class="buttons"></div>');
                    const $title = $('<h3>' + track.name + '</h3>');

                    // Создаем кнопку Play/Pause с data-track-id
                    const $playPauseButton = $(`
                        <button class="play-pause-button" data-track-id="${track.id}">
                            <img src="../static/icons/play.webp" alt="Play">
                        </button>
                    `).click(function () {
                        togglePlayPause(track, $(this));
                    });

                    // Добавляем кнопку копирования только если original_url присутствует
                    if (track.original_url) {
                        const $copyButton = $('<button><img src="../static/icons/copy.webp" alt="Copy"></button>').click(function () {
                            copyToClipboard(track.original_url); // Копируем оригинальную ссылку
                        });
                        $buttons.append($copyButton);
                    }

                    const $descriptionButton = $('<button><img src="../static/icons/description.webp" alt="Description"></button>').click(function () {
                        showDescription(track);
                    });
                    const $deleteButton = $('<button><img src="../static/icons/close.webp" alt="Delete"></button>').click(function () {
                        deleteTrack(track.id, track.name);
                    });

                    $topDiv.append($playPauseButton).append($title);
                    $buttons.append($descriptionButton).append($deleteButton);
                    $trackTile.append($topDiv).append($buttons);
                    $tracksContainer.append($trackTile);
                });
            }
            renderPagination();
        }).fail(function (jqxhr, textStatus, error) {
            console.error('Ошибка при загрузке треков:', error);
            alert('Не удалось загрузить треки.');
        });
    }

    function togglePlayPause(track, $button) {
        if (currentTrackId === track.id) {
            // Если тот же трек, переключаем воспроизведение/пауза
            if ($audioControl[0].paused) {
                $audioControl[0].play();
                $button.find('img').attr('src', '../static/icons/pause.webp');
            } else {
                $audioControl[0].pause();
                $button.find('img').attr('src', '../static/icons/play.webp');
            }
        } else {
            // Если другой трек
            // Останавливаем текущий трек, если есть
            if (currentTrackId !== null && $currentPlayButton !== null) {
                $currentPlayButton.find('img').attr('src', '../static/icons/play.webp');
            }

            // Устанавливаем новый трек
            currentTrackId = track.id;
            $currentPlayButton = $button;
            $audioControl.attr('src', track.url);
            $trackTitle.text(track.name);
            $audioControl[0].play();  // Воспроизведение

            // Меняем иконку кнопки
            $button.find('img').attr('src', '../static/icons/pause.webp');
        }
        maximizePlayer();
    }

    function maximizePlayer() {
        $audioPlayer.removeClass('minimized').addClass('maximized');
        $togglePlayerButton.addClass('rotated');
    }

    function minimizePlayer() {
        $audioPlayer.addClass('minimized').removeClass('maximized');
        $togglePlayerButton.removeClass('rotated');
    }

    function showDescription(track) {
        $descriptionTitle.text(track.name);
        $descriptionText.text(track.description || 'Нет описания.');
        $descriptionDialog.fadeIn(animationSpeed);
    }

    /**
     * Функция для отображения уведомления.
     * @param {string} message - Текст уведомления.
     */
    function showNotification(message) {
        const $notification = $('<div class="notification"></div>').text(message);
        $('#notifications-container').append($notification);

        // Запустить анимацию появления
        setTimeout(() => {
            $notification.addClass('show');
        }, 10); // Небольшая задержка для корректного срабатывания CSS

        // Удалить уведомление через 1.5 секунды
        setTimeout(() => {
            $notification.removeClass('show').addClass('hide');
            // Удалить элемент из DOM после завершения анимации
            $notification.on('transitionend', () => {
                $notification.remove();
            });
        }, 1500);
    }

    function copyToClipboard(text) {
        if (navigator.clipboard) {
            navigator.clipboard.writeText(text).then(function() {
                showNotification('Ссылка скопирована!');
            }).catch(function(err) {
                console.error('Не удалось скопировать:', err);
                fallbackCopy(text); // Вызываем fallback, если Clipboard API не сработал
            });
        } else {
            fallbackCopy(text);
        }
    }

    function fallbackCopy(text) {
        const textArea = document.createElement('textarea');
        textArea.value = text;
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();

        try {
            const successful = document.execCommand('copy');
            if (successful) {
                showNotification('Ссылка скопирована!');
            } else {
                showNotification('Не удалось скопировать ссылку.');
            }
        } catch (err) {
            console.error('Ошибка при копировании fallback:', err);
            showNotification('Не удалось скопировать ссылку.');
        }

        document.body.removeChild(textArea);
    }

    function deleteTrack(trackId, trackName) {
        if (confirm(`Вы уверены, что хотите удалить трек "${trackName}"?`)) {
            $.ajax({
                url: `/tracks/${trackId}`,
                type: 'DELETE',
                success: function (data) {
                    if (data.error) {
                        showNotification('Ошибка: ' + data.error);
                    } else {
                        showNotification(data.message);
                        // Если удаляется текущий воспроизводимый трек, сбрасываем аудио
                        if (currentTrackId === trackId) {
                            $audioControl[0].pause();
                            $audioControl.attr('src', '');
                            $trackTitle.text('');
                            if ($currentPlayButton !== null) {
                                $currentPlayButton.find('img').attr('src', '../static/icons/play.webp');
                                $currentPlayButton = null;
                            }
                            currentTrackId = null;
                        }
                        loadTracks(currentPage, currentSearch);
                    }
                },
                error: function (jqxhr, textStatus, error) {
                    console.error('Ошибка при удалении трека:', error);
                    showNotification('Что-то пошло не так.');
                }
            });
        }
    }

    // Рендеринг элементов пагинации
    function renderPagination() {
        const totalPages = Math.ceil(totalTracks / perPage);
        $paginationControls.empty();

        if (totalPages <= 1) return;

        // Кнопка "Предыдущая"
        const $prevButton = $('<button>').text('<< Предыдущая').prop('disabled', currentPage === 1).click(function () {
            if (currentPage > 1) {
                loadTracks(currentPage - 1, currentSearch);
            }
        });
        $paginationControls.append($prevButton);

        // Номера страниц (отображать максимум 5)
        const maxPagesToShow = 5;
        let startPage = Math.max(1, currentPage - Math.floor(maxPagesToShow / 2));
        let endPage = startPage + maxPagesToShow - 1;
        if (endPage > totalPages) {
            endPage = totalPages;
            startPage = Math.max(1, endPage - maxPagesToShow + 1);
        }

        for (let i = startPage; i <= endPage; i++) {
            const $pageButton = $('<button>').text(i).addClass(i === currentPage ? 'active' : '').click(function () {
                loadTracks(i, currentSearch);
            });
            $paginationControls.append($pageButton);
        }

        // Кнопка "Следующая"
        const $nextButton = $('<button>').text('Следующая >>').prop('disabled', currentPage === totalPages).click(function () {
            if (currentPage < totalPages) {
                loadTracks(currentPage + 1, currentSearch);
            }
        });
        $paginationControls.append($nextButton);
    }

    // --- Обработчики Событий ---

    // Открытие диалога добавления трека
    $addTrackButton.click(function () {
        $addTrackDialog.fadeIn(animationSpeed);
    });
    $closeAddDialog.click(function () {
        $addTrackDialog.fadeOut(animationSpeed);
    });

    // Закрытие диалогового окна описания
    $closeDescriptionDialog.click(function () {
        $descriptionDialog.fadeOut(animationSpeed);
    });

    // Закрытие модальных окон при клике вне их
    $(window).click(function (event) {
        if (event.target == $addTrackDialog[0]) {
            $addTrackDialog.fadeOut(animationSpeed);
        }
        if (event.target == $descriptionDialog[0]) {
            $descriptionDialog.fadeOut(animationSpeed);
        }
    });

    // Добавление нового тега
    $addTagButton.click(function () {
        const $tagItem = $('<div class="tag-item"></div>');
        const $tagInput = $('<input type="text" name="tags">');
        const $removeButton = $('<button type="button"><img src="../static/icons/close.webp" alt="Удалить тег"></button>').click(function () {
            $tagItem.remove();
        });
        $tagItem.append($tagInput).append($removeButton);
        $tagsContainer.append($tagItem);
    });

    // Обработка выбора файла через input
    $trackFileInput.on('change', function () {
        const file = this.files[0];
        if (file) {
            $selectedFileName.text(file.name);
            $selectedFileInfo.removeClass('hidden');
        } else {
            $selectedFileInfo.addClass('hidden');
            $selectedFileName.text('');
        }
    });

    // Обработка удаления выбранного файла
    $removeSelectedFile.click(function () {
        $trackFileInput.val(''); // Очищаем выбранный файл

        // Создаем пустой DataTransfer для очистки FileList
        const dataTransfer = new DataTransfer();
        $trackFileInput[0].files = dataTransfer.files;

        $selectedFileName.text('');
        $selectedFileInfo.addClass('hidden');
    });

    // Отправка формы добавления трека с файлом
    $addTrackForm.submit(function (event) {
        event.preventDefault();

        const formData = new FormData(this);

        // Валидация: проверяем наличие файла
        if (!formData.get('file')) {
            showNotification('Файл трека обязателен.');
            return;
        }

        $.ajax({
            url: '/tracks',
            type: 'POST',
            data: formData,
            processData: false, // Не обрабатываем данные
            contentType: false, // Не устанавливаем contentType
            success: function (data) {
                if (data.error) {
                    showNotification('Ошибка: ' + data.error);
                } else {
                    showNotification('Трек успешно добавлен!');
                    $addTrackDialog.fadeOut(animationSpeed);
                    $addTrackForm[0].reset();
                    $tagsContainer.empty();
                    $selectedFileInfo.addClass('hidden');
                    loadTracks(1, {}); // Перезагрузка первой страницы без поиска
                }
            },
            error: function (jqxhr, textStatus, error) {
                console.error('Ошибка при добавлении трека:', error);
                const response = jqxhr.responseJSON;
                if (response && response.error) {
                    showNotification('Ошибка: ' + response.error);
                } else {
                    showNotification('Что-то пошло не так.');
                }
            }
        });
    });

    // Обработка dragover и dragleave для file-drop-area
    $fileDropArea.on('dragover', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).addClass('hover');
    });

    $fileDropArea.on('dragleave', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).removeClass('hover');
    });

    $fileDropArea.on('drop', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).removeClass('hover');

        const files = e.originalEvent.dataTransfer.files;
        if (files.length > 0) {
            // Создаем объект DataTransfer и добавляем файл
            const dataTransfer = new DataTransfer();
            dataTransfer.items.add(files[0]);

            // Устанавливаем созданный FileList в input
            $trackFileInput[0].files = dataTransfer.files;

            // Отображаем информацию о выбранном файле
            $selectedFileName.text(files[0].name);
            $selectedFileInfo.removeClass('hidden');
        }
    });

    // Переключение состояния проигрывателя
    $togglePlayerButton.click(function () {
        $audioPlayer.toggleClass('minimized maximized');
        $togglePlayerButton.toggleClass('rotated');
    });

    // Копирование ссылки в проигрывателе (если реализовано)
    // Если есть элемент для копирования ссылки в плеере, реализуйте соответствующую логику здесь
    // Например:
    /*
    $copyLinkButton.click(function () {
        const trackId = $(this).closest('.track-tile').find('.play-pause-button').data('track-id');
        const track = getTrackById(trackId);
        if (track && track.original_url) {
            copyToClipboard(track.original_url);
        } else {
            showNotification('Нет ссылки для копирования.');
        }
    });
    */

    // Отправка формы поиска
    $searchForm.submit(function (event) {
        event.preventDefault();
        const name = $('#search-name').val().trim();

        currentSearch = {name};
        loadTracks(1, currentSearch);
    });

    // Очистка поиска
    $clearSearchButton.click(function () {
        $searchForm[0].reset();
        currentSearch = {name: '', description: '', tags: []};
        loadTracks(1, currentSearch);
    });

    // Обработчик ввода в поисковой строке
    $('#search-name').on('input', function () {
        const name = $(this).val().trim();
        currentSearch = {name};
        loadTracks(1, currentSearch);
    });

    // Обработчик окончания воспроизведения трека
    $audioControl.on('ended', function () {
        if (currentTrackId !== null && $currentPlayButton !== null) {
            $currentPlayButton.find('img').attr('src', '../static/icons/play.webp');
            currentTrackId = null;
            $currentPlayButton = null;
        }
        minimizePlayer();
    });

    // Обработчик события воспроизведения трека
    $audioControl.on('play', function () {
        if (currentTrackId !== null && $currentPlayButton !== null) {
            $currentPlayButton.find('img').attr('src', '../static/icons/pause.webp');
        }
    });

    // Обработчик события паузы трека
    $audioControl.on('pause', function () {
        if (currentTrackId !== null && $currentPlayButton !== null) {
            $currentPlayButton.find('img').attr('src', '../static/icons/play.webp');
        }
    });

    // Функции для обработки глобального перетаскивания файлов
    let dragCounter = 0; // Добавляем счетчик перетаскиваний

    function showGlobalOverlay() {
        $globalOverlay.removeClass('hidden').addClass('fade-in').removeClass('fade-out');
    }

    function hideGlobalOverlay() {
        $globalOverlay.removeClass('fade-in').addClass('fade-out');
        // После анимации скрываем
        setTimeout(() => {
            $globalOverlay.removeClass('fade-out').addClass('hidden');
        }, 300);
    }

    // Обработка dragenter
    $(document).on('dragenter', function (e) {
        e.preventDefault();
        e.stopPropagation();
        dragCounter++;
        showGlobalOverlay();
    });

    // Обработка dragleave
    $(document).on('dragleave', function (e) {
        e.preventDefault();
        e.stopPropagation();
        dragCounter--;
        if (dragCounter === 0) {
            hideGlobalOverlay();
        }
    });

    // Обработка dragover
    $(document).on('dragover', function (e) {
        e.preventDefault();
        e.stopPropagation();
        // Можно дополнительные действия при перетаскивании
    });

    // Обработка drop
    $(document).on('drop', function (e) {
        e.preventDefault();
        e.stopPropagation();
        dragCounter = 0;
        hideGlobalOverlay();

        const files = e.originalEvent.dataTransfer.files;
        if (files.length > 0) {
            // Проверяем, является ли первый файл аудио
            const audioFile = Array.from(files).find(file => file.type.startsWith('audio/'));
            if (audioFile) {
                $addTrackDialog.fadeIn(animationSpeed);
                // Создаем объект DataTransfer и добавляем файл
                const dataTransfer = new DataTransfer();
                dataTransfer.items.add(audioFile);

                // Устанавливаем созданный FileList в input
                $trackFileInput[0].files = dataTransfer.files;

                // Отображаем информацию о выбранном файле
                $selectedFileName.text(audioFile.name);
                $selectedFileInfo.removeClass('hidden');
            } else {
                showNotification('Пожалуйста, перетащите аудио-файл.');
            }
        }
    });

    // Получение трека по ID (для копирования ссылки)
    function getTrackById(trackId) {
        return allTracks.find(track => track.id === trackId) || null;
    }

    // Первоначальная загрузка треков
    loadTracks();
});
```
Аудио не воспроизводится, ошибка что файл не найден

Вот например `http://127.0.0.1:6390/tracks/d12d650a-e2f0-472e-8071-2c1089226cb8_ppp1.wav` - не найден