Современный мир пресыщен различной информацией, и в наше непростое время её важно уметь не только находить и сохранять. Многие наверняка заметили, что в на YouTube, кроме мусора, котиков и прочих бесполезных вещей (которые мы иногда не прочь посмотреть) есть масса полезного материала по самым различным темам. И иногда этот материал неплохо было бы сохранить себе на будущее, чтобы не зависеть от переменчивых настроений в мире.

В этой статье я хочу рассказать, как можно скачивать видео, аудио (1 часть статьи), плейлисты и целые каналы с YouTube (2 часть статьи) без использования VPN и на чистом Python-е. Сразу оговорка: VPN нам не понадобится, но мы сделаем собственное средство, которое будет решать "проблему с устаревшим и изношенным оборудованием Google Global Cache" (вы поняли, о чём я). Я думаю это средство будет особенно актуально сегодня, когда у многих россиян YouTube почти или совсем не работает.


Зачем изобретать велосипед и почему Python?

  1. Я программирую на Python, и о чём мне рассказывать как не о нём?

  2. У python есть широкие возможности для создания таких инструментов и готовые библиотеки с большим функционалом.

  3. Существуют такие замечательные утилиты, как yt-dlp и youtube-dl, но они подходят, когда нужно по-быстрому что-то скачать. Тонкая настройка и скачивание, например целого канала, вещь довольно геморройная (если, нет - поправьте меня), так как постоянно нужно что-то гуглить и знать многочисленные ключи и параметры.

  4. Существуют и другие десктопные программы, мобильные приложения и сайты, но как правило они или платные, или напичканы рекламой, или ограничены в функционале, или даже всё вместе.

  5. Ну и по-моему, собственный скрипт всегда удобнее любой навороченной утилиты, да и глаз радуется на красивые строчки в редакторе)

Этап 1. Обходим блок… ой!.. Решаем проблему с устаревшим и изношенным оборудованием.

Почему YouTube у нас работает не так, как надо? Конечно, все знают, что дело здесь не в оборудовании, а в том, что провайдеры используют такую зловредную (в данном случае) вещь, как DPI (англ. Deep Packet Inspection «глубокая инспекция пакетов»)

How it works

Большинство DPI работает так. Когда вы пытаетесь получить доступ к заблокированному веб-сайту, DPI отправляет вам HTTP 302 Redirect, и делает это быстрее, чем веб-сайт к которому вы обращаетесь. В отличие от брандмауэров, Deep Packet Inspection анализирует не только заголовки пакетов, но и содержимое запросов, что позволяет интернет-провайдерам и государственным органам ограничивать доступ к запрещенным ресурсам, выявлять вторжения в сеть и останавливать распространение компьютерных вирусов.

Это довольно упрощенная модель пассивного DPI, но так как целью этой статьи не является подробное ознакомление с этой темой, да и я, честно признаюсь, не большой специалист в этом, то думаю этого достаточно для понимания того, что происходит. Если вас интересует эта тема, то можете почитать здесь и здесь.

Что же делать

Но, на каждый болт найдется своя гайка, и есть способы обойти эту вещь (хотя они не всегда действуют). Многие наверняка слышали про GoodbyeDPI или zapret. Это замечательные инструменты, но раз уж мы говорим про Python, то давайте сделаем свой аналог на Python. Поискав немного, я нашел nodpi, который использует только python.

Как это работает

nodpi создает прокси-сервер (socket), через который мы гоним трафик. Все исходящие соединения он случайным образом фрагментирует, тем самым сбивая с толку DPI.

Плюсы

  1. Это написано на Python!

  2. Просто, дёшево, сердито и работает для большинства провайдеров

  3. Не требуются привилегии администратора, как, например у GoodbyeDPI

  4. Прокси-сервер можно настроить только в некоторых приложениях и не гнать через него весь трафик системы.

Минусы

  1. Простота - не всегда качество, поэтому гарантия не даётся

  2. Работает только для TCP

  3. Не поможет, если сайт забанен по IP

Пишем..., нет - переписываем код

Программа написана довольно небрежно, словно у разработчика слипались глаза и он залил код прямо так, не разбираясь, и поэтому я приведу причёсанный код и заодно немного расскажу, что он делает.

Для начала создадим текстовый файл blacklist.txt и добавим туда домены, блокировку которых хотим обходить. Для YouTube это:

youtube.com
youtu.be
yt.be
googlevideo.com
ytimg.com
ggpht.com
gvt1.com
youtube-nocookie.com
youtube-ui.l.google.com
youtubeembeddedplayer.googleapis.com
youtube.googleapis.com
youtubei.googleapis.com
yt-video-upload.l.google.com
wide-youtube.l.google.com

Теперь создадим файл nodpi.py и добавим в него следующий код

import random
import asyncio

BLOCKED = [line.rstrip().encode() for line in open('blacklist.txt', 'r', encoding='utf-8')]
TASKS = []

Что мы здесь делаем:

  1. Импортируем необходимые библиотеки

  2. Создаём список заблокированных доменов

  3. Создаём список, в котором будем хранить задачи передачи данных между клиентом и сервером

async def main(host, port):

    server = await asyncio.start_server(new_conn, host, port)
    await server.serve_forever()

Создаём входную точку - асинхронную функцию, которая запускает сокет-сервер на указанном хосте и порту и используем new_conn (ниже) для обработки новых соединений.

async def pipe(reader, writer):

    while not reader.at_eof() and not writer.is_closing():
        try:
            writer.write(await reader.read(1500))
            await writer.drain()
        except:
            break

    writer.close()

Создаём асинхронную функцию, которая читает данные из reader и записывает их в writer до тех пор, пока не достигнут конец или соединение не закрыто.

async def new_conn(local_reader, local_writer):

    http_data = await local_reader.read(1500)

    try:
        type, target = http_data.split(b"\r\n")[0].split(b" ")[0:2]
        host, port = target.split(b":")
    except:
        local_writer.close()
        return

    if type != b"CONNECT":
        local_writer.close()
        return

    local_writer.write(b'HTTP/1.1 200 OK\n\n')
    await local_writer.drain()

    try:
        remote_reader, remote_writer = await asyncio.open_connection(host, port)
    except:
        local_writer.close()
        return

    if port == b'443':
        await fragemtn_data(local_reader, remote_writer)

    TASKS.append(asyncio.create_task(pipe(local_reader, remote_writer)))
    TASKS.append(asyncio.create_task(pipe(remote_reader, local_writer)))
  1. Создаём асинхронную функцию, которая обрабатывает новое соединение.

  2. Читаем HTTP-заголовки и извлекаем тип запроса и целевой адрес.

  3. Если тип запроса не CONNECT, закрываем соединение.

  4. Отправляем ответ HTTP/1.1 200 OK клиенту.

  5. Открываем соединение с целевым сервером.

  6. Если порт равен 443 (порт HTTPS), вызываем функцию fragemtn_data (ниже)

  7. Создаем задачи для передачи данных между клиентом и сервером.

async def fragemtn_data(local_reader, remote_writer):

    head = await local_reader.read(5)
    data = await local_reader.read(1500)
    parts = []

    if all([data.find(site) == -1 for site in BLOCKED]):
        remote_writer.write(head + data)
        await remote_writer.drain()

        return

    while data:
        part_len = random.randint(1, len(data))
        parts.append(bytes.fromhex("1603") + bytes([random.randint(0, 255)]) + int(
            part_len).to_bytes(2, byteorder='big') + data[0:part_len])

        data = data[part_len:]

    remote_writer.write(b''.join(parts))
    await remote_writer.drain()
  1. Создаём асинхронную функцию, которая фрагментирует данные перед отправкой на сервер.

  2. Читаем заголовок и данные.

  3. Если данные не из заблокированных доменов, отправляем их без изменений.

  4. В противном случае, разбиваем данные на случайные части и добавляем заголовки перед отправкой. Это помогает обойти блокировку DPI, так как фрагментированные данные выглядят как случайные пакеты.

asyncio.run(main(host='127.0.0.1', port=8881))

Запускаем сервер на локальном 127.0.0.1 и слушаем порт 8881

Всё, можно пользоваться!

Давайте проверим. Если у вас Firefox, то заходим в Настройки → Настройки сети и прописываем IP и порт:

Настройка прокси в Firefox
Настройка прокси в Firefox

Открываем YouTube и убеждаемся, что все работает или не работает :)

Этап 2. Скачиваем!

Установка необходимого инструментария

Для начала установим библиотеку pytubefix командой:

pip install pytubefix
Немного о pytubefix

pytubefix - это мощная библиотека python для скачивания с YouTube видео, аудио, плейлистов и каналов со своим собственным cli. Сама по себе она фактически является форком pytube, но последние изменения в pytube были сделаны больше года назад, и в августе этого года, после изменений в api YouTube она перестала работать. Также в pytubefix исправлены многие недочеты предшественницы и добавлены новые функции. pytubefix, как и pytube, работает с api youtube, а кое-где и парсит его html/json.

Также нам понадобится ffmpeg, для объединения аудио и видео (если, конечно, вы хотите скачивать в высоком качестве). Почему? Дело в том, что YouTube дает видео с аудио в одном потоке только в разрешении 360p (раньше было 720p), и чтобы скачать видео, например в 1080p, нужно сначала скачать видео в 1080p, потом скачать аудио, и затем все это объединить конвертером. ffmpeg существует и для Windows. Проверенную сборку можно скачать с моего Google Диска, но вы можете найти ее и самостоятельно в интернете.

Простая загрузка видео

Давайте попробуем скачать какое-нибудь видео. Создайте файл yt_downloader.py и вставьте в него код:

from pytubefix import YouTube
from pytubefix.cli import on_progress

url = "https://www.youtube.com/watch?v=xxxxxxxxxxx"

video = YouTube(
    proxies={"http": "http://127.0.0.1:8881",
             "https": "http://127.0.0.1:8881"},
    url=url,
    on_progress_callback=on_progress,
)

print('Title:', yt.title)

stream = video.streams.get_highest_resolution()
stream.download()

Давайте разберём, что делает этот код. Сначала мы импортируем класс YouTube, с помощью которого мы скачиваем видео, и функцию on_progress. Она нужна для того, чтобы во время скачивания отображался прогрессбар загрузки. Согласитесь, что так гораздо удобнее? При желании можно написать свою функцию-callback. Она должна иметь аргументы (stream: Stream, chunk: bytes, bytes_remaining: int)

В переменную url вставьте свою ссылку для скачивания, так как я заменил id видео иксами. Далее мы создаем экземпляр класса YouTube и передаем ему словарь с адресом нашего прокси-сервера, url и callback. Все аргументы, кроме url являются необязательными. Также стоит отметить, что callback вызывается каждый раз, после скачивания нового чанка (pytubefix скачивает видео кусками - чанками).

Далее мы выводим на экран заголовок (название) видео. Также можно узнать дату публикации, длину видео (в секундах), описание, количество просмотров и автора. Размер файла можно узнать с помощью stream.filesize, так как он зависит от выбранного потока.

В строке stream = video.streams.get_highest_resolution() мы получаем список потоков и сортируем его по разрешению (качеству) видео. Тут я хочу остановиться и рассказать немного подробнее. У каждого видео на YouTube есть несколько десятков потоков, каждый из которых представляет собой одно видео, одно аудио или все сразу в разных форматах, кодировках и качестве. Так, для моего видео список потоков выглядит примерно так:

Осторожно, длинная портянка!
[
    {
        "itag": 18,
        "mime_type": "video/mp4",
        "resolution": "360p",
        "vcodec": "avc1.42001E",
        "acodec": "mp4a.40.2",
        "progressive": True,
        "type": "video",
    },
    {
        "itag": 315,
        "mime_type": "video/webm",
        "resolution": "2160p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 337,
        "mime_type": "video/webm",
        "resolution": "2160p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 701,
        "mime_type": "video/mp4",
        "resolution": "2160p",
        "vcodec": "av01.0.13M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 308,
        "mime_type": "video/webm",
        "resolution": "1440p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 336,
        "mime_type": "video/webm",
        "resolution": "1440p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 700,
        "mime_type": "video/mp4",
        "resolution": "1440p",
        "vcodec": "av01.0.12M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 299,
        "mime_type": "video/mp4",
        "resolution": "1080p",
        "vcodec": "avc1.64002a",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 303,
        "mime_type": "video/webm",
        "resolution": "1080p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 335,
        "mime_type": "video/webm",
        "resolution": "1080p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 699,
        "mime_type": "video/mp4",
        "resolution": "1080p",
        "vcodec": "av01.0.09M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 298,
        "mime_type": "video/mp4",
        "resolution": "720p",
        "vcodec": "avc1.4d4020",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 302,
        "mime_type": "video/webm",
        "resolution": "720p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 334,
        "mime_type": "video/webm",
        "resolution": "720p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 698,
        "mime_type": "video/mp4",
        "resolution": "720p",
        "vcodec": "av01.0.08M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 135,
        "mime_type": "video/mp4",
        "resolution": "480p",
        "vcodec": "avc1.4d401f",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 244,
        "mime_type": "video/webm",
        "resolution": "480p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 333,
        "mime_type": "video/webm",
        "resolution": "480p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 697,
        "mime_type": "video/mp4",
        "resolution": "480p",
        "vcodec": "av01.0.05M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 134,
        "mime_type": "video/mp4",
        "resolution": "360p",
        "vcodec": "avc1.4d401e",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 243,
        "mime_type": "video/webm",
        "resolution": "360p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 332,
        "mime_type": "video/webm",
        "resolution": "360p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 696,
        "mime_type": "video/mp4",
        "resolution": "360p",
        "vcodec": "av01.0.04M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 133,
        "mime_type": "video/mp4",
        "resolution": "240p",
        "vcodec": "avc1.4d4015",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 242,
        "mime_type": "video/webm",
        "resolution": "240p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 331,
        "mime_type": "video/webm",
        "resolution": "240p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 695,
        "mime_type": "video/mp4",
        "resolution": "240p",
        "vcodec": "av01.0.01M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 160,
        "mime_type": "video/mp4",
        "resolution": "144p",
        "vcodec": "avc1.4d400c",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 278,
        "mime_type": "video/webm",
        "resolution": "144p",
        "vcodec": "vp9",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 330,
        "mime_type": "video/webm",
        "resolution": "144p",
        "vcodec": "vp9.2",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 694,
        "mime_type": "video/mp4",
        "resolution": "144p",
        "vcodec": "av01.0.00M.10.0.110.09.18.09.0",
        "acodec": None,
        "progressive": False,
        "type": "video",
    },
    {
        "itag": 139,
        "mime_type": "audio/mp4",
        "resolution": None,
        "vcodec": None,
        "acodec": "mp4a.40.5",
        "progressive": False,
        "type": "audio",
    },
    {
        "itag": 140,
        "mime_type": "audio/mp4",
        "resolution": None,
        "vcodec": None,
        "acodec": "mp4a.40.2",
        "progressive": False,
        "type": "audio",
    },
    {
        "itag": 249,
        "mime_type": "audio/webm",
        "resolution": None,
        "vcodec": None,
        "acodec": "opus",
        "progressive": False,
        "type": "audio",
    },
    {
        "itag": 250,
        "mime_type": "audio/webm",
        "resolution": None,
        "vcodec": None,
        "acodec": "opus",
        "progressive": False,
        "type": "audio",
    },
    {
        "itag": 251,
        "mime_type": "audio/webm",
        "resolution": None,
        "vcodec": None,
        "acodec": "opus",
        "progressive": False,
        "type": "audio",
    },
]

Вы можете посмотреть полный список потоков для своего видео, просто выведя на экран print(video.streams), но как правило это не требуется, так как библиотека предоставляет средства для их сортировки и фильтрации. В нашем случае это get_highest_resolution(). Эта функция возвращает поток с самым лучшим разрешением, который содержит и аудио, и видео. Как я уже объяснял, таким разрешением окажется 360p, потому что YouTube дает видео с аудио в одном потоке только в разрешении 360p (раньше было 720p), и чтобы скачать видео, например в 1080p, нужно сначала скачать видео в 1080p, потом скачать аудио, и затем все это объединить конвертером. Скрипт, который скачивает видео в более высоком качестве, мы напишем чуть позднее.

Ну и наконец, в строке stream.download() мы скачиваем видео. При скачивании будет отображаться прогрессбар, и вы увидите процесс загрузки.

Запустите скрипт и посмотрите результат. Не забудьте перед этим запустить нашу программу для обхода DPI!

Скачиваем видео в высоком разрешении

Видео в 360p, это, конечно, не очень. Давайте расширим нашу программу. Если вы еще не скачали ffmpeg, сделайте это. Без него скачивание в другом расширении невозможно. Предполагается, что ffmpeg лежит в той же папке, что и скрипт.

Создайте файл yt_downloader_2.py и добавьте в него следующий код:

import os

from pytubefix import YouTube
from pytubefix.cli import on_progress

url = "https://www.youtube.com/watch?v=xxxxxxxxxxx"


def combine(audio: str, video: str, output: str) -> None:

    if os.path.exists(output):
        os.remove(output)

    code = os.system(
        f'.\\ffmpeg.exe -i "{video}" -i "{audio}" -c copy "{output}"')

    if code != 0:
        raise SystemError(code)


def download(url: str):

    yt = YouTube(
        proxies={"http": "http://127.0.0.1:8881",
                 "https": "http://127.0.0.1:8881"},
        url=url,
        on_progress_callback=on_progress,
    )

    video_stream = yt.streams.\
        filter(type='video').\
        order_by('resolution').\
        desc().first()

    audio_stream = yt.streams.\
        filter(mime_type='audio/mp4').\
        order_by('filesize').\
        desc().first()

    print('Information:')
    print("\tTitle:", yt.title)
    print("\tAuthor:", yt.author)
    print("\tDate:", yt.publish_date)
    print("\tResolution:", video_stream.resolution)
    print("\tViews:", yt.views)
    print("\tLength:", round(yt.length/60), "minutes")
    print("\tFilename of the video:", video_stream.default_filename)
    print("\tFilesize of the video:", round(
        video_stream.filesize / 1000000), "MB")

    print('Download video...')
    video_stream.download()
    print('\nDownload audio...')
    audio_stream.download()

    combine(audio_stream.default_filename, video_stream.default_filename,
            f'{yt.title}.mp4')


download(url)

Что изменилось? Мы добавили функцию combine, которая отвечает за объединение видео и аудио. Мы делаем это командой .\ffmpeg.exe -i "filename_video" -i "filename_audio" -c copy "output_filename"

В основном коде мы по отдельности вытаскиваем потоки видео и аудио. Здесь видео не содержит аудио, но зато оно в высоком качестве. Чтобы получить его, мы сначала фильтруем потоки по типу (видео) filter(type='video'),  затем сортируем по разрешению, затем сортируем по убыванию разрешения и берём первый поток. Аналогично с аудио. После этого мы выводим подробную информацию о скачиваемом видео и скачиваем аудио и видео по отдельности, после чего объединяем их с помощью ffmpeg. Ничего сложного!

Запускаем наш скрипт для обхода DPI и скрипт для скачивания (замените url на свой). Готово!

Как узнать список доступных разрешений

Чтобы узнать, в каких разрешениях можно скачать данное видео, можно написать такую функцию:

def resolutions(video: YouTube):

    res = []

    streams = self.video.streams.\
                    filter(type='video').\
                    order_by('resolution').\
                    desc()

    for stream in streams:
        if stream.resolution not in res:
            res.append(stream.resolution)

    return res    
  

Поток с выбранным разрешением можно получить следующим образом:

res = '1080p' # например
stream = self.video.streams.\
          filter(resolution=res, progressive=False).desc().first()

Если вы не используете ffmpeg, замените progressive=False на True

Скачивание аудио

Из предыдущего примера вы видели, как мы скачивали аудио:

...

audio_stream = yt.streams.\
        filter(mime_type='audio/mp4').\
        order_by('filesize').\
        desc().first()

audio_stream.download()

Только учтите, что формат аудио будет m4a, поэтому, если вам нужен другой, придётся воспользоваться ffmpeg


На этом я хочу остановиться. В следующей части (если такая будет) я расскажу о том, как скачивать целые плейлисты, каналы и даже субтитры с YouTube.

Известные проблемы

Обход DPI не работает

Да, такое, конечно, возможно. Но у меня на провайдере ТТК всё работает отлично. Поэтому я могу лишь посоветовать использовать другие инструменты, например GoodbyeDPI.

Remote end closed connection

А вот это действительно проблема, с которой я столкнулся. Она появилась, когда начали тормозить YouTube и я перешёл на nodpi. То ли ютуб банит подозрительную активность, то ли РКН химичит, а может в nodpi что-то не так. Я так и не понял. Если тут есть знатоки, может подскажут, что не так и как пофиксить)

Предупреждение

Если статья вам интересна, не откладывайте её в долгий ящик, так как через некоторое время после публикации она может попасть под географические ограничения по запросу РКН

Комментарии (50)


  1. MAXH0
    26.12.2024 15:51

    Я планирую, наоборот:

    1. Сохранить.

    2. Отложить в долгий ящик до Нового Года

    3. Опробовать.

    4. Разобрать на элементы.

    5. Показать школьникам - благо они уже интересовались.

    6. ПРОФИТ?

    PS Если к Интернету совсем не придет ЧеБуратор после НГ....

    PSS И, разумеется, спасибо Вам за Работу. Как раз хотел скачать ряд аудио дорожек с ютуба, чтобы не зависеть от замедляторов. Ваше решение кажется мне почти идеальным.


  1. Repinson
    26.12.2024 15:51

    Очень полезная статья. Спасибо.


  1. Yoti
    26.12.2024 15:51

    вызываем функцию fragemtn_data

    Даже название функции фрагментировано!


    1. Zzzz9
      26.12.2024 15:51

      Это тенденция такая, сейчас все так называют https://github.com/theo0x0/nodpi/blob/main/nodpi.py#L57


    1. vova_sam
      26.12.2024 15:51

      и потихоньку фиксится поставщиками ТСПУ (только сейчас понял, что "угрозы" в официальном названии этого устройства обозначает пользователей youtube. Т.е. угроза исходит от тех, кто смотрит видео )

      статья отличная. но именно для школьников ,чтобы мышление развивалось. практическое использование его близко к нулю


  1. eugenk
    26.12.2024 15:51

    Спасибо ! Полезная статья. Сам я сейчас смотрю через Tor Browser. Всё великолепно работает ! Ни платных VPN, ни каких-то левых расширений. Единственно что поначалу опечалило, пошли рекламные вставки от ютуба. Но поставил на тор addBlock, и это тоже исчезло. Сейчас смотрю как до блокировки. Москва, МГТС, GPON.

    Географические ограничения тору тоже не помеха.


    1. DoubleSystems
      26.12.2024 15:51

      Братка а скорость какая? 360px?


      1. eugenk
        26.12.2024 15:51

        Да нормальная скорость и нормальное качество. Как до начала блокировок.


        1. eugenk
          26.12.2024 15:51

          Мне вот чисто познавательно интересно, тот кто поставил минус, сам пробовал через тор посмотреть ??? Или просто от большого ума ???


          1. Lord_of_Rings Автор
            26.12.2024 15:51

            Скорее от малого. Но это точно не я)


          1. itshnick88
            26.12.2024 15:51

            Я по началу тоже пытался через TOR, даже на телек его поставил, но столкнулся с проблемой: периодически теряется соединение, приходится перезапускать браузер и устанавливать его заново - а устанавливается оно минут 20-30 - просто висит, как будто ничего не происходит, но потом, в фоне, подцепляется к мостам (мосты всегда актуальные использую). И конечно, после этого всегда приходится снова входить в аккаунт гугла на ютубе, проходить все многофакторки... что вкупе создаёт неприятный геморрой, когда нужно посмотреть какое-то видео желательно сейчас, а приходится ждать минут 30, поэтому пришлось перейти на proxy (который почему-то называют VPN-ом, но никакие сети он, конечно, не строит)

            Тор остался на прозапас как запасной вариант


          1. AlexSpirit
            26.12.2024 15:51

            Ну я пробовал смотреть. 240-360px.


          1. vagonovozhaty
            26.12.2024 15:51

            Вероятно те, у кого сайты в Торе еле шевелятся, когда вы YouTube в 4К смотрите


      1. VerityFreedom
        26.12.2024 15:51

        Скорость свежего начисто поставленного Тора скорее рандомна и зависит от того к каким мостам он достучится, и как дальше пойдёт соединение. Понятное дело что это будет медленнее чем то что он способен из себя выжать в идеальных условиях как минимум в пару раз даже с поправкой на агрессивную среду российской федерации, но я вполне верю, что там если повезёт будет и 20 mb/s, а это уже фуллхд без прогрузок. Надо сравнить ибо у меня есть как специализированная сборка так и браузер.


    1. neit_kas
      26.12.2024 15:51

      А у вас Tor не блокируют? Я по осени брал ванильную сборку (т.е. не совершал какие-то доп. телодвижения), не работало. Как понял, тоже РКН что-то где-то блокировал. Какой-то внятной инструкции по этому поводу не нашёл. Точнее даже так: "Добавьте сервера". Где брать список серверов - не нашёл.


      1. vicsoftware
        26.12.2024 15:51

        Телеграм


      1. Apasnychel
        26.12.2024 15:51

        Мосты, @tor_briges

        Это в тг бот, вставляем, выбираем obfs4


        1. dimonier
          26.12.2024 15:51

          Такое имя не найдено, а если "мосты" написать правильно, то находится


          1. vova_sam
            26.12.2024 15:51

            как они интересно имя без суффикса _bot получили?

            лично Павел помог?


            1. Aelliari
              26.12.2024 15:51

              из любопытства поискал, мне поиск не показал бота без суффикса «bot», но вообще если имя преобразовано через платформу fragment - его отдельно можно «улучшить», и после этого можно будет присваивать ботам


      1. VerityFreedom
        26.12.2024 15:51

        У меня есть такой список проименованных мостов на полторы сотни позиций работающих и даже неработающих на новейшем протоколе. В Тор не так давно прикрутили собственную реализацию влесса поэтому блокировать его никто не умеет совершенно, а старые протоколы не могут победить из-за их количества. Правда не так давно snowflake грохнули, люди делают свою работу.


    1. VerityFreedom
      26.12.2024 15:51

      Я с начала года пишу модифицированный Тор который можно поставить в любой браузер через расширение с автонастройкой по синхронизации к файлу у меня на Гитхаб. 4К 60 в принципе со скрипом тянет без подгрузок. Но прикол в том что это далеко не простой Тор а ядро от него, поэтому реализовано полное раздельное туннелирование.


    1. VerityFreedom
      26.12.2024 15:51

      Щас чекнул, Тор и в браузере, и в моей сборке которая на совсем иных принципах создания соединения построена, выжимает чуть выше 40 mb/s, а этого с головой.


    1. Jack_Lupino
      26.12.2024 15:51

      Странно, тоже Москва, МГТС GPON, но Tor давно уже не подключается, только через VPN начинает работать


    1. Okeu
      26.12.2024 15:51

      Это первое решение - на тор перейти, или уже пробовали gdpi/zapret? и они перестали работать?


      1. vova_sam
        26.12.2024 15:51

        в зависимости от оператора. После вопроса блогера с бумагой в голове стало работать намного хуже


  1. Mustafa_Abdullah
    26.12.2024 15:51

    Пойду друзьям рассказывать, что смотрю ютуб через змею


  1. hdrk
    26.12.2024 15:51

    Спасибо за скрипт, РТК, МТС не пробивает, а ТТК как раз пробивает)


    1. Lord_of_Rings Автор
      26.12.2024 15:51

      Только ТТК не говорите...


      1. hdrk
        26.12.2024 15:51

        по идее ТТК ничего не должен сделать, ибо все это замедляет оборудование неподвластное ему...


  1. Rastishka
    26.12.2024 15:51

    Эх, сделал бы кто скрипт чтобы можно было на условный кинетик одной командой ставить (типа как outline). И обновлять автоматом список доменов.

    Я бы даже задонатил.


    1. alexdora
      26.12.2024 15:51

      del


  1. mister_xen
    26.12.2024 15:51

    Не ну в статье явно обман.

    Поясняю: Когда используете магическую палочку, то вы используете далекие датацентры. А если в рф сервера ютуба деградировали, что бы ты не написал и как не извернулся, то ты же обращаешься к этим деградированным серверам.


    1. NotMusk
      26.12.2024 15:51

      Это вы немного не понимаете ситуации. Да, серверов GGC стало меньше в РФ (примерно в 2 раза). Да, это вызывает некоторое замедление из-за более частых обращений к холодным серверам YouTube. Но это очень незначительное замедление. Но зато это значительный внешний трафик через западных магистралов, за что надо платить провайдерам денежку.

      Поэтому да, любой обход DPI вернет практически всю старую скорость YouTube, но при этом сделает наших провайдеров чуточку беднее.


    1. net_racoon
      26.12.2024 15:51

      Вам щас сколько за такие комментарии платят?


  1. Javian
    26.12.2024 15:51

    Remote end closed connection

    буквально недавно видео стало воспроизводиться ровно одну минуту и останавливаться.

    У меня подозрение, что это в РКН сделано против скрипта GoodCheck - подборки параметров запуска goodbyeDPI. Для скрипта первая минута выглядит как удачный обход блокировки.


    1. SatelliteCat
      26.12.2024 15:51

      Мне кажется, что это уже на стороне ютуба - там по идее должна быть реклама, возможно как-то определяет, что не может её воспроизвести. На некоторых впнах нормально видео воспроизводится, а на некоторых на 59 секунде зависает.
      С goodbyeDPI иногда приходится перезагружать страницу несколько раз, чтобы видео начало воспроизводиться, но проблем с первой минутой нет. Запускаю `1_russia_blacklist_YOUTUBE_ALT.cmd` с ключом -6 вместо 5.


      1. Javian
        26.12.2024 15:51

        С ходу -6 не повлиял как и предыдущие разы игры с параметрами. Пока отложил до выходных. Попробую в Wireshark наблюдать.


        1. Okeu
          26.12.2024 15:51

          у меня с гудбаем давно все отвалилось, Goodcheck гонял, уже не помню сколько там максимум было SUCCESS'ов, но все они касались прочих сайтов из блоклиста, адреса ютуба были почти по нулям) В итоге воткнул себе вторым сервисом Zapret от FlowSeal - с ним все ок.


    1. VADemon
      26.12.2024 15:51

      По одной минуте отсекался также клиент NewPipe и Youtube Revanced, когда его обфускацию задетектили. Я тоже мнения, что это со стороны YT.


    1. piton_nsk
      26.12.2024 15:51

      Это что-то со стороны ютуба. Началась такая же фигня, нормального решения пока не нашел, но нашлись обсуждения в инете с такой же проблемой. Такая фигня не только в РФ.


    1. phdoafin
      26.12.2024 15:51

      Юзаю Тор для Ютуба и такая проблема тоже стала появляться, именно на одной минуте останавливается. Заметил что на таких видео не показывается реклама вначале, нажимаю "создать новую цепочку для этого сайта" и если вначале видео есть реклама все ок.