Как скачать видео с youtube-dl непосредственно на стороне пользователя, а не скачивать файл в локальной системе, используя python Django?

Я пытаюсь видео с youtube объединить с аудио(formate_id:140) и видео(formate_id:313) с помощью библиотеки youtube-dl. Но она загружает файлы в локальную систему. Я хочу, чтобы он напрямую загружал файлы на стороне клиента. Я не хочу хранить файлы в локальной системе.

Client-side означает загрузку файлов непосредственно в систему пользователя через браузер.

Локальная система означает, что это мой сервер.

Пример

ydl_opts = {
    'format': '313+140',
    'keepvideo':'false',
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/watch?v=Wt8VRxUYDso'])

Если какой-либо способ, такой как процесс слияния и процесс потоковой передачи ответа, работает одновременно.

r = requests.get(videoUrl, stream=True)
response = StreamingHttpResponse(streaming_content=r)
response['Content-Disposition'] = f'attachement; filename="{fileName}"'
return response

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

После некоторого исследования я нашел опцию для youtube_dl под названием progress_hooks, которая получает downloaded_bytes, похожую на байтовый буфер какого-то типа (точно не нашел в документации).

Этот хук может быть использован для отправки каждого буфера как чанка в Django StreamingHttpResponse. Проблема в том, что он ожидает получить данные с помощью генератора, переданного в streaming_content аргументе.

Поэтому нам понадобился способ превратить хук обратного вызова в генератор. Это похоже на процесс загрузки FTP клиента. Я использовал это также с этим замечательным ответом и пришел к чему-то вроде:

from queue import Queue

from django.http import StreamingHttpResponse
import youtube_dl


def my_view(request):
    q = Queue()
    job_done = object()

    def process_bytes(progress):
        if progress["status"] == "downloading":
            byte_chunk = progress["downloaded_bytes"]
            q.put(byte_chunk)
            q.join()
        elif progress["status"] == "finished":
            q.put(job_done)

    ydl_opts = {
        'format': '313+140',
        'keepvideo': 'false',
        'progress_hooks': [process_bytes],
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download(['https://www.youtube.com/watch?v=Wt8VRxUYDso'])

    def chunk_consumer():
        while True:
            chunk = q.get(True, None)  # block, no timeout
            if chunk is job_done:
                break
            else:
                yield chunk
                q.task_done()

    return StreamingHttpResponse(streaming_content=chunk_consumer())

В любом случае, я не совсем уверен, сможет ли клиент (браузер или js) собрать фрагменты в файл.

Вернуться на верх