Как скачать видео с 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) собрать фрагменты в файл.