循环音频帧并存储在队列/容器中

问题描述 投票:0回答:1

我有一个要求,我需要构建类似流媒体程序的东西,其中我的程序定期接收分成多个块的视频;说2秒。 我的每个包含音频的视频都是 10 秒。现在,每当我收到视频时,我都会将其添加到全局或共享容器中,我可以从中继续读取并在 python 中连续播放视频,而不会导致用户遇到任何延迟。

程序尚未构建,我仍在弄清楚其中的细节。在下面的代码中,我通过浏览多个答案和博客尝试了类似的方法。我正在为当前在整个视频/音频帧上循环的单个视频执行此操作并将其存储在容器中。然而,这种使用

ffpyplayer
的方法不起作用,并且由于某种原因,无法像处理视频帧那样一一处理音频帧。

我怎样才能达到同样的效果?在下面的程序中,我如何首先存储视频和音频帧,然后遍历它们并使它们播放/显示?

from ffpyplayer.player import MediaPlayer
from ffpyplayer.pic import Image
import cv2

video_path  = "output_1.mp4"
player = MediaPlayer(video_path)

# Initialize a list to store frames and audio frames
media_queue = []  # A temporary queue to store frames and audio frames
frame_index = 0   # To keep track of the frame index

cap = cv2.VideoCapture(video_path)

while True:
    ret, frame = cap.read()
    audio_frame, val_audio = player.get_frame()   # Get the next audio frame

    if ret != 'eof' and frame is not None:
        img = frame 
        media_queue.append(('video', img))
    if val_audio != 'eof' and audio_frame is not None:
        audio = audio_frame[0] 
        media_queue.append(('audio', audio))

    if ret == 'eof' and val_audio == 'eof':
        break

    frame_index += 1

print(f"Total frames and audio frames processed: {frame_index}")

# Play Frames and Audio from Queue
for media_type, media_data in media_queue:
    if media_type == 'video':
        img_data = Image(media_data[0], media_data[1])
        cv2.imshow("Frame", img_data.image)  # Display the frame
    elif media_type == 'audio':
        player.set_volume(1.0)
        player.set_audio_frame(media_data)

    if cv2.waitKey(25) & 0xFF == ord("q"):  
        break

cv2.destroyAllWindows() 

我知道上面的程序是错误的。有没有办法通过首先将视频和音频存储到某个容器中然后循环访问它来流式传输视频和音频?即使有人可以帮助我提供算法并解释我应该查看的内容,我也可以尝试使其发挥作用。

python video-streaming audio-streaming ffpyplayer
1个回答
0
投票

您似乎想构建一个程序,定期接收视频和音频块并无缝播放它们,没有任何延迟。您使用

ffpyplayer
的方法是一个良好的开始,但需要进行一些调整才能实现您的目标。

首先,让我们概述一个可以实现视频和音频同步的流媒体播放的算法:

  1. 接收视频和音频块:

    • 定期(例如每 2 秒)接收新的视频和音频块。
  2. 存储块:

    • 将接收到的视频和音频块同步存储在队列中。您可以使用自定义数据结构来保存视频和音频数据,也可以对视频和音频使用单独的队列。
  3. 循环播放:

    • 启动播放循环,不断从同步队列中检索帧。
    • 对于循环的每次迭代:
      • 如果队列中有视频帧,则显示它。
      • 如果队列中有音频帧,则播放它。

考虑到这个算法,让我们相应地修改您的代码:

from ffpyplayer.player import MediaPlayer
from ffpyplayer.pic import Image
import cv2
import time
import queue

video_path = "output_1.mp4"
player = MediaPlayer(video_path)

# Initialize a queue to store synchronized media chunks
media_queue = queue.Queue()

# Start a separate thread to receive and add chunks to the queue
# This thread should add both video and audio chunks to the queue

# Simulating chunks being received and added to the queue
for i in range(10):
    video_chunk = ...  # Receive video chunk
    audio_chunk = ...  # Receive audio chunk
    media_queue.put(('video', video_chunk))
    media_queue.put(('audio', audio_chunk))
    time.sleep(2)  # Simulating a 2-second interval

# Main playback loop
while True:
    try:
        media_type, media_data = media_queue.get(timeout=1)
    except queue.Empty:
        break

    if media_type == 'video':
        img_data = Image(media_data[0], media_data[1])
        cv2.imshow("Frame", img_data.image)  # Display the frame
    elif media_type == 'audio':
        player.set_volume(1.0)
        player.set_audio_frame(media_data)

    if cv2.waitKey(25) & 0xFF == ord("q"):
        break

cv2.destroyAllWindows()

在此代码中,主要变化是使用循环模拟媒体块,您可以将其替换为实际的块接收机制。播放循环不断处理和显示视频帧并播放同步队列中的音频帧。

希望有帮助!!

© www.soinside.com 2019 - 2024. All rights reserved.