2013-10-21 21 views
14

Tôi đã nhận cả OpenCV và PyAudio nhưng tôi không chắc chắn về cách đồng bộ hóa chúng với nhau. Tôi không thể nhận được tốc độ khung hình từ OpenCV và đo thời gian gọi cho một khung hình thay đổi theo từng thời điểm. Tuy nhiên với PyAudio cơ sở của nó là lấy một tỷ lệ mẫu nhất định. Làm cách nào để đồng bộ hóa chúng với cùng tốc độ. Tôi giả sử có một số codec tiêu chuẩn hoặc một số cách làm điều đó. (Tôi đã thử google tất cả tôi đã nhận được thông tin về đồng bộ môi: /).Đồng bộ hóa âm thanh và video với OpenCV và PyAudio

tỷ lệ OpenCV Khung

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 

Grabbing và tiết kiệm audio

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

Trong trường hợp bạn đã cài đặt 'pyffmpeg' hoạt động, bạn có thể thử sử dụng khả năng hiển thị video (và âm thanh) của' ffmpeg', thay vì sử dụng OpenCV để hiển thị video. – boardrider

Trả lời

1

Tôi nghĩ rằng bạn muốn được tốt hơn bằng cách sử dụng GSreamer hoặc ffmpeg, hoặc nếu bạn đang ở trên Windows, DirectShow. Các thư viện này có thể xử lý cả âm thanh và video và phải có một số loại Bộ ghép kênh để cho phép bạn kết hợp video và âm thanh đúng cách.

Nhưng nếu bạn thực sự muốn làm điều này bằng cách sử dụng Opencv, bạn sẽ có thể sử dụng VideoCapture để có tốc độ khung hình, bạn đã thử sử dụng this chưa?

fps = cv.GetCaptureProperty(vc, CV_CAP_PROP_FPS) 

Một cách khác là để ước lượng fps như số khung chia theo độ dài:

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; 

Tôi không chắc tôi hiểu những gì bạn đang cố gắng làm ở đây:

before_read = time.time() 
rval, frame = vc.read() 
after_read = time.time() 

Dường như với tôi rằng việc thực hiện after_read - before_read chỉ đo thời gian để OpenCV tải khung tiếp theo, nó không đo lường khung hình/giây. OpenCV không cố gắng phát lại, nó chỉ tải khung hình và nó sẽ cố gắng làm như vậy nhanh nhất có thể và tôi nghĩ không có cách nào để cấu hình nó. Tôi nghĩ rằng đặt một waitKey(1/fps) sau khi hiển thị mỗi khung hình sẽ đạt được những gì bạn đang tìm kiếm.

+0

@ Zimm3r Ứng dụng có hoạt động không? –

+0

Mặc dù điều này rất muộn, nhưng tôi không sử dụng GStreamer vì có những mục tiêu cụ thể mà tôi muốn tiếp cận và gặp rắc rối với GStreamer trong quá khứ. – Zimm3r

Các vấn đề liên quan