2013-10-21 4 views
14

OpenCV와 PyAudio를 모두 사용할 수있게되었지만 어떻게 동기화 할 것인지 잘 모르겠습니다. OpenCV에서 프레임 속도를 얻을 수없고 프레임의 호출 시간을 측정하는 것이 순간마다 바뀝니다. 그러나 PyAudio를 사용하면 특정 샘플 속도를 얻는 것이 기본입니다. 같은 속도로 동기화하려면 어떻게해야합니까? 나는 코덱이 그것을하는 약간 기준 또는 어떤 방법다는 것을 추측한다. (나는 입술 동기화에 관한 정보를 얻었습니다 : /).OpenCV와 PyAudio로 오디오와 비디오 동기화하기

OpenCV의 프레임 속도

from __future__ import division 
import time 
import math 
import cv2, cv 

vc = cv2.VideoCapture(0) 
# get the frame 
while True: 

    before_read = time.time() 
    rval, frame = vc.read() 
    after_read = time.time() 
    if frame is not None: 
     print len(frame) 
     print math.ceil((1.0/(after_read - before_read))) 
     cv2.imshow("preview", frame) 

     if cv2.waitKey(1) & 0xFF == ord('q'): 
      break 

    else: 
     print "None..." 
     cv2.waitKey(1) 

# display the frame 

while True: 
    cv2.imshow("preview", frame) 

    if cv2.waitKey(1) & 0xFF == ord('q'): 
     break 

from sys import byteorder 
from array import array 
from struct import pack 

import pyaudio 
import wave 

THRESHOLD = 500 
CHUNK_SIZE = 1024 
FORMAT = pyaudio.paInt16 
RATE = 44100 

def is_silent(snd_data): 
    "Returns 'True' if below the 'silent' threshold" 
    print "\n\n\n\n\n\n\n\n" 
    print max(snd_data) 
    print "\n\n\n\n\n\n\n\n" 
    return max(snd_data) < THRESHOLD 

def normalize(snd_data): 
    "Average the volume out" 
    MAXIMUM = 16384 
    times = float(MAXIMUM)/max(abs(i) for i in snd_data) 

    r = array('h') 
    for i in snd_data: 
     r.append(int(i*times)) 
    return r 

def trim(snd_data): 
    "Trim the blank spots at the start and end" 
    def _trim(snd_data): 
     snd_started = False 
     r = array('h') 

     for i in snd_data: 
      if not snd_started and abs(i)>THRESHOLD: 
       snd_started = True 
       r.append(i) 

      elif snd_started: 
       r.append(i) 
     return r 

    # Trim to the left 
    snd_data = _trim(snd_data) 

    # Trim to the right 
    snd_data.reverse() 
    snd_data = _trim(snd_data) 
    snd_data.reverse() 
    return snd_data 

def add_silence(snd_data, seconds): 
    "Add silence to the start and end of 'snd_data' of length 'seconds' (float)" 
    r = array('h', [0 for i in xrange(int(seconds*RATE))]) 
    r.extend(snd_data) 
    r.extend([0 for i in xrange(int(seconds*RATE))]) 
    return r 

def record(): 
    """ 
    Record a word or words from the microphone and 
    return the data as an array of signed shorts. 

    Normalizes the audio, trims silence from the 
    start and end, and pads with 0.5 seconds of 
    blank sound to make sure VLC et al can play 
    it without getting chopped off. 
    """ 
    p = pyaudio.PyAudio() 
    stream = p.open(format=FORMAT, channels=1, rate=RATE, 
     input=True, output=True, 
     frames_per_buffer=CHUNK_SIZE) 

    num_silent = 0 
    snd_started = False 

    r = array('h') 

    while 1: 
     # little endian, signed short 
     snd_data = array('h', stream.read(1024)) 
     if byteorder == 'big': 
      snd_data.byteswap() 

     print "\n\n\n\n\n\n" 
     print len(snd_data) 
     print snd_data 

     r.extend(snd_data) 

     silent = is_silent(snd_data) 

     if silent and snd_started: 
      num_silent += 1 
     elif not silent and not snd_started: 
      snd_started = True 

     if snd_started and num_silent > 1: 
      break 

    sample_width = p.get_sample_size(FORMAT) 
    stream.stop_stream() 
    stream.close() 
    p.terminate() 

    r = normalize(r) 
    r = trim(r) 
    r = add_silence(r, 0.5) 
    return sample_width, r 

def record_to_file(path): 
    "Records from the microphone and outputs the resulting data to 'path'" 
    sample_width, data = record() 
    data = pack('<' + ('h'*len(data)), *data) 

    wf = wave.open(path, 'wb') 
    wf.setnchannels(1) 
    wf.setsampwidth(sample_width) 
    wf.setframerate(RATE) 
    wf.writeframes(data) 
    wf.close() 

if __name__ == '__main__': 
    print("please speak a word into the microphone") 
    record_to_file('demo.wav') 
    print("done - result written to demo.wav") 
+1

작동중인'pyffmpeg '가있는 경우 비디오 디스플레이에 OpenCV를 사용하는 대신'ffmpeg'의 비디오 (및 오디오) 디스플레이 기능을 사용해보십시오. – boardrider

답변

1

난 당신이 GSreamer 또는는 FFmpeg 또는 Windows에서 경우의 DirectShow를 사용하여 더 나을 거라고 생각 오디오 잡아 및 저장. 이 라이브러리는 오디오와 비디오를 모두 처리 할 수 ​​있으며, 비디오와 오디오를 적절하게 믹싱 할 수있는 일종의 멀티플렉서가 있어야합니다.

Opencv를 사용하여 실제로이 작업을 수행하려면 VideoCapture을 사용하여 프레임 속도를 얻을 수 있어야합니다. this을 사용해 보셨습니까?

before_read = time.time() 
rval, frame = vc.read() 
after_read = time.time() 
: 나는 당신이 여기에서 뭘하려고했는지 이해가 확실하지 않다

nFrames = cv.GetCaptureProperty(vc, CV_CAP_PROP_FRAME_COUNT) 
      cv.SetCaptureProperty(vc, CV_CAP_PROP_POS_AVI_RATIO, 1) 
duration = cv.GetCaptureProperty(vc, CV_CAP_PROP_POS_MSEC) 
fps = 1000 * nFrames/duration; 

:

fps = cv.GetCaptureProperty(vc, CV_CAP_PROP_FPS) 

또 다른 방법은 시간으로 나눈 프레임 수로 FPS를 추정하는 것

after_read - before_read은 OpenCV가 다음 프레임을로드하는 데 걸리는 시간 만 측정하며 fps는 측정하지 않습니다. OpenCV는 재생을하려고하지 않습니다. 프레임을로드하는 것일 뿐이므로 최대한 빨리 재생하려고합니다. 구성 할 방법이 없다고 생각합니다. 각 프레임을 표시 한 후 waitKey(1/fps)을 넣으면 원하는 것을 얻을 수 있다고 생각합니다.

+0

@ Zimm3r 작동합니까? –

+0

비록 매우 늦었지만, 과거에 GStreamer에 도달하고 싶었던 특정 목표가 있었기 때문에 GStreamer를 사용하지 않았습니다. – Zimm3r