Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在不下载视频的情况下提取youtube视频的特定帧_Python_Opencv_Ffmpeg_Video Capture_Youtube Dl - Fatal编程技术网

Python 在不下载视频的情况下提取youtube视频的特定帧

Python 在不下载视频的情况下提取youtube视频的特定帧,python,opencv,ffmpeg,video-capture,youtube-dl,Python,Opencv,Ffmpeg,Video Capture,Youtube Dl,我需要提取一个在线视频的特定帧来处理一个算法,但我不想下载整个视频,因为这会使它效率非常低 首先,我尝试使用youtube视频。我可以通过以下方式使用youtube dl下载整个视频: ydl_opts = {'outtmpl': r'OUTPUT_DIRECTORY_HERE',} with youtube_dl.YoutubeDL(ydl_opts) as ydl: ydl.download([url]) 然后,我可以捕捉单个帧 我需要避免下载整个视频。经过一些研究,我发现ffmp

我需要提取一个在线视频的特定帧来处理一个算法,但我不想下载整个视频,因为这会使它效率非常低

首先,我尝试使用youtube视频。我可以通过以下方式使用youtube dl下载整个视频:

ydl_opts = {'outtmpl': r'OUTPUT_DIRECTORY_HERE',}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download([url])
然后,我可以捕捉单个帧

我需要避免下载整个视频。经过一些研究,我发现ffmpeg可能会帮助我做到这一点。我没有办法只下载帧,所以如果这不可能,第二个选择是我可以下载视频的特定部分。linux中的一个这样的例子是,但我找不到python的任何解决方案

用python下载视频的帧或部分而不下载整个内容的好方法是什么?

我尝试了@AyeshaKhan在评论中分享的内容

导入cv2、numpy、youtube dl后:

评论中的答案是下载所有帧,因此我添加的计数。格式确保我根据要求跳过帧

此外,这里的x将数字限制为10

尽管如此,我仍然不确定这个方法是否真的捕获了指定的帧,或者它是否捕获了所有帧并将指定的帧保存到本地存储中。我需要前者


但这仍然足够快,适合我

除了当前的答案之外,还可以使用多处理进一步提高性能。例如,如果要将视频分割为帧,并在num_cpu进程中独立处理它们:

import os
from functools import partial
from multiprocessing.pool import Pool

import cv2
import youtube_dl

def process_video_parallel(url, skip_frames, process_number):
    cap = cv2.VideoCapture(url)
    num_processes = os.cpu_count()
    frames_per_process = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) // num_processes
    cap.set(cv2.CAP_PROP_POS_FRAMES, frames_per_process * process_number)
    x = 0
    count = 0
    while x < 10 and count < frames_per_process:
        ret, frame = cap.read()
        if not ret:
            break
        filename =r"PATH\shot"+str(x)+".png"
        x += 1
        cv2.imwrite(filename.format(count), frame)
        count += skip_frames  # Skip 300 frames i.e. 10 seconds for 30 fps
        cap.set(1, count)
    cap.release()



video_url = "..."  # The Youtube URL
ydl_opts = {}
ydl = youtube_dl.YoutubeDL(ydl_opts)
info_dict = ydl.extract_info(video_url, download=False)

formats = info_dict.get('formats', None)

print("Obtaining frames")
for f in formats:
    if f.get('format_note', None) == '144p':
        url = f.get('url', None)
        cpu_count = os.cpu_count()
        with Pool(cpu_count) as pool:
            pool.map(partial(process_video_parallel, url, 300), range(cpu_count))

在本应用程序中,由于图像只是从视频中保存的,这可能不会在几秒钟内带来巨大的改进,但如果需要在帧上应用其他算法,这可能是有益的。

。这有帮助吗?@AyeshaKhan这个答案正在下载所有的画面。所以我做的就是跳过了下载,比如说我在视频中每隔300帧下载一帧,也就是说,每10秒下载一帧30帧的视频。这似乎奏效了。尽管如此,我不确定我是否只是跳过了本地保存它们,还是实际上跳过了捕获它们。谢谢你!我已经构建了一个API来获取youtube视频的帧:。它需要http请求并返回映像。
import os
from functools import partial
from multiprocessing.pool import Pool

import cv2
import youtube_dl

def process_video_parallel(url, skip_frames, process_number):
    cap = cv2.VideoCapture(url)
    num_processes = os.cpu_count()
    frames_per_process = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) // num_processes
    cap.set(cv2.CAP_PROP_POS_FRAMES, frames_per_process * process_number)
    x = 0
    count = 0
    while x < 10 and count < frames_per_process:
        ret, frame = cap.read()
        if not ret:
            break
        filename =r"PATH\shot"+str(x)+".png"
        x += 1
        cv2.imwrite(filename.format(count), frame)
        count += skip_frames  # Skip 300 frames i.e. 10 seconds for 30 fps
        cap.set(1, count)
    cap.release()



video_url = "..."  # The Youtube URL
ydl_opts = {}
ydl = youtube_dl.YoutubeDL(ydl_opts)
info_dict = ydl.extract_info(video_url, download=False)

formats = info_dict.get('formats', None)

print("Obtaining frames")
for f in formats:
    if f.get('format_note', None) == '144p':
        url = f.get('url', None)
        cpu_count = os.cpu_count()
        with Pool(cpu_count) as pool:
            pool.map(partial(process_video_parallel, url, 300), range(cpu_count))