i bought an USB microphone and a Camera module for the raspberry pi4. I managed to record Audio and Video but when i merge them with ffmpeg the are not synchronized, i'm trying to solve this for 2 days now.
Here my code, when the program starts it record video with the instruction "camera.start_recording("Video.h264")", this instruction return immediatly so when the program executes the instruction after camera.start_recording("Video.h264") the video is still recording.
For recording Audio i use a while loop that stops when i press a button. When i press the button the video recording also stops.
After everything is written i use ffmpeg to merge the video (After converting it to mp4) and the Audio.
# coding=utf-8
from picamera import PiCamera
import pyaudio
import wave
import os
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
print("Ready")
go = True
camera = PiCamera()
camera.resolution = (1920, 1080)
audio = pyaudio.PyAudio()
stream = audio.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True)
frames = []
camera.start_recording("Video.h264")
while go:
print("Recording")
if GPIO.input(10) == GPIO.HIGH:
camera.stop_recording()
go = False
print("Recording has been stopped")
data = stream.read(1024, exception_on_overflow = False)
frames.append(data)
stream.stop_stream()
stream.close()
audio.terminate()
sound_file = wave.open("Audio.wav", "wb")
sound_file.setnchannels(1)
sound_file.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
sound_file.setframerate(44100)
sound_file.writeframes(b''.join(frames))
sound_file.close()
print("Converting in mp4")
os.system("ffmpeg -i Video.h264 Video.mp4")
print("Merging audio and video")
os.system("ffmpeg -i Video.mp4 -i Audio.wav -c:v copy -c:a aac vea.mp4")
Related
I'm a bit new to Python and I'm developping an application for a Raspberry Pi where a motion sensor is connected.
The idea is to place this Raspberry in a room and on motion detection a video starts playing fullscreen.
After the video is done playing I want to let the device sleep for 10 minutes and than activate the motion sensor again to play the same video again. The screen also should stay black after the video so not quiting the vlc application and see the Raspberry Pi Desktop.
So far I tried some code where in one file the fullscreen works, and in the other file the loop works, but bringing the 2 files togheter is giving errors.
As I said I'm very new to coding so it could be the problem is very stupid and the solution very simple. Thanks in advance for the help.
Down below my 2 code-files.
Option 1 (fullscreen not working)
from gpiozero import MotionSensor, LED
from time import sleep
import vlc
# creating Instance class object
player = vlc.Instance()
# creating a new media list
media_list = player.media_list_new()
# creating a media player object
media_player = player.media_list_player_new()
# creating a new media
media = player.media_new("/home/pi/MOSA25.mp4")
# adding media to media list
media_list.add_media(media)
# setting media list to the mediaplayer
media_player.set_media_list(media_list)
# setting loop
player.vlm_set_loop("1", True)
#fullscreen
#media_player.set_fullscreen(True)
#Motion Sensor
pir = MotionSensor(4)
#Led
led = LED(26)
led.off()
print("Sensor loading.")
pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
pir.wait_for_motion()
print("Motion detected")
led.on()
sleep(5)
led.off()
media_player.play()
sleep(30)
OPTION 2 (Loop not working)
from gpiozero import MotionSensor, LED
from time import sleep
import vlc
# creating Instance class object
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
player.set_mrl("/home/pi/MOSA25.mp4")
player.set_fullscreen(True)
# setting loop
#player.vlm_set_loop("1", True)
#Motion Sensor
pir = MotionSensor(4)
#Led
led = LED(26)
led.off()
print("Sensor wordt geladen.")
pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
pir.wait_for_motion()
print("Motion detected")
led.on()
sleep(5)
led.off()
player.play()
sleep(20)
Keep track of the video playing in another while loop and reload before starting again.
Here's your code (adjusted as I don't have your kit)
from time import sleep
import vlc
playing = set([1,2,3,4])
# creating Instance class object
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
player.set_fullscreen(True)
#Motion Sensor
#pir = MotionSensor(4)
#Led
#led = LED(26)
#led.off()
print("Sensor wordt geladen.")
#pir.wait_for_no_motion()
sleep(5)
while True:
print("Ready")
# pir.wait_for_motion()
sleep(1)
print("Motion detected")
# led.on()
sleep(1)
# led.off()
player.set_mrl("/home/pi/MOSA25.mp4")
player.play()
sleep(1)
while player.get_state() in playing:
sleep(1)
continue
print("Finished")
sleep(5)
continue
I am recording audio using sounddevice and I want to play it through a virtual audio cable through pygame, I keep receiving this error Exception has occurred: error mpg123_seek: Invalid RVA mode. (code 12)
My code is below:
import sounddevice as sd
from scipy.io.wavfile import write
import random
import pygame
import time
pygame.init()
pygame.mixer.init(devicename='CABLE Input (VB-Audio Virtual Cable)')
fs = 44100 # Sample rate
seconds = 00.1 # Duration of recording
def main():
for x in range(10000):
number = random.randint(1,9999999)
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
write(f'output/output{str(number)}.mp3', fs, myrecording) # Save as WAV file `
# PLAY MIC SOUND HERE
pygame.mixer.music.load(f'output/output{str(number)}.mp3') #Load the mp3
pygame.mixer.music.play() #Play it
time.sleep(00.1)
main()
Any help is appreciated.
There's a couple of issues.
The first is that scipi.io.wavefile.write() only writes an uncompressed WAV file (ref: https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.write.html ). You might name it .mp3, but it's not compressed that way.
The next issue is that pygame.mixer.music will not .load() uncompressed WAV files. So... what to do...
One work-around is to use the base pygame.mixer, which is happy to load uncompressed WAV. And while I don't have an 'CABLE Input (VB-Audio Virtual Cable)' device, I do get a nice file of silence, which I validated with the sound-editing program Audacity, and this seems to play OK.
import sounddevice as sd
from scipy.io.wavfile import write
import pygame
import time
import random
pygame.init()
pygame.mixer.init(devicename='CABLE Input (VB-Audio Virtual Cable)')
fs = 44100 # Sample rate
seconds = 00.1 # Duration of recording
def main():
for x in range(10000):
number = random.randint(1,9999999)
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
filename = f'output/output{str(number)}.wav'
write(filename, fs, myrecording) # Save as uncompressed WAV file
# PLAY MIC SOUND HERE
print( "Playing [" + filename + "]" )
#pygame.mixer.music.load(filename) #Load the wav
#pygame.mixer.music.play() #Play it
#while ( pygame.mixer.music.get_busy() ): # wait for the sound to end
# time.sleep(00.1)
sound = pygame.mixer.Sound(filename) #Load the wav
sound.play() #Play it
while ( pygame.mixer.get_busy() ): # wait for the sound to end
time.sleep(00.1)
main()
How do I stop the audio playing through playaudio module in Python code?
I have played music but I can't stop that music. How can I stop it?
playsound.playsound("name_of_file")
You can use the multiprocessing module to play the sound as a background process, then terminate it anytime you want:
import multiprocessing
from playsound import playsound
p = multiprocessing.Process(target=playsound, args=("file.mp3",))
p.start()
input("press ENTER to stop playback")
p.terminate()
Playsound is a single function module that plays sounds, and nothing else. It would seem that means it does not stop playing sounds either. From their own documentation:
The playsound module contains only one thing - the function (also named) playsound.
Personally, I like to use pyaudio. The following code is adapted from the example here. The code plays audio and has the space bar set as a pause/play button.
import pyaudio
import wave
import time
from pynput import keyboard
paused = False # global to track if the audio is paused
def on_press(key):
global paused
print (key)
if key == keyboard.Key.space:
if stream.is_stopped(): # time to play audio
print ('play pressed')
stream.start_stream()
paused = False
return False
elif stream.is_active(): # time to pause audio
print ('pause pressed')
stream.stop_stream()
paused = True
return False
return False
# you audio here
wf = wave.open('audio\\songs\\And_Your_Bird_Can_Sing_mp3_2_wav.wav', 'rb')
# instantiate PyAudio
p = pyaudio.PyAudio()
# define callback
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
return (data, pyaudio.paContinue)
# open stream using callback
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
# start the stream
stream.start_stream()
while stream.is_active() or paused==True:
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
time.sleep(0.1)
# stop stream
stream.stop_stream()
stream.close()
wf.close()
# close PyAudio
p.terminate()
On windows try:
import winsound
winsound.PlaySound(r'C:\sound.wav', winsound.SND_ASYNC)
Stop Playback:
winsound.PlaySound(None, winsound.SND_PURGE)
#pip install pygame
from pygame import mixer
import time
mixer.init() #Initialzing pyamge mixer
mixer.music.load('lovingly-618.mp3') #Loading Music File
mixer.music.play() #Playing Music with Pygame
time.sleep(5)
mixer.music.stop()
Here is a much easier way:
wmp = win32com.client.dynamic.Dispatch("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 100
wmp.URL = file
while globals()["allowSound"]:
PumpWaitingMessages()
You can change globals()["allowSound"] from another thread and set it to false when the audio has ended (you can get the length of the audio with wmp.durationString)
Here is some more info about this: Windows Media Player COM Automation works from VBS but not from Python
Although this does not use the playsound module it is a good alternative.
After successful execution of the program, audio file will start playing. Now Click on terminal, once you see the cursor, type Ctrl+C, it will bring you out of the terminal and audio will also stop playing.
Programming Instructions used:
from playsound import playsound
playsound('//path//to//a//sound//file//you//want//to//play.mp3')
EASY......
on your terminal tab, look for kill(delete) option on the right hand side.
click the delete option and it will stop playing
I am using Adafruit I2S MEMS Microphone Breakout for recording. ref. https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout?view=all
When i wire the Mic to RPI in Mono configuration as per below image I am able record audio using arecord command and below python code
arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v recording.wav
Python Code snippet:
channels=1, rate=48000, frames_per_buffer=2400
def start_recording(self):
try:
self.logger.info("start_recording()> enter")
# Use a stream with a callback in non-blocking mode
self._stream = self._pa.open(format=pyaudio.paInt32,
channels=self.channels,
rate=self.rate,
input=True,
frames_per_buffer=self.frames_per_buffer,
stream_callback=self.get_callback())
self._stream.start_stream()
self.logger.info("start_recording()> exit")
return self
except Exception, e:
self.logger.error("start_recording()>", exc_info = True)
But If I connect channel selection pin to logic high vltage i am able to record audio using arecord command but uanble to record using python code.
Any changes required in python code to record right channel mono audio?
I did something similar but using python-sounddevice. Here's my repo
EDIT:
here is the specific audio recording class for clarification
import threading
import queue
import numpy
import sounddevice as sd
import soundfile as sf
class AudioRecorder():
def __init__(self):
self.open = True
self.file_name = 'name_of_file.wav'
self.channels = 1
self.q = queue.Queue()
# Get samplerate
device_info = sd.query_devices(2, 'input')
self.samplerate = int(device_info['default_samplerate'])
def callback(self, indata, frames, time, status):
# This is called (from a separate thread) for each audio block.
if status:
print(status, file=sys.stderr)
self.q.put(indata.copy())
def record(self):
with sf.SoundFile(self.file_name, mode='x', samplerate=self.samplerate, channels=self.channels) as file:
with sd.InputStream(samplerate=self.samplerate, channels=self.channels, callback=self.callback):
while(self.open == True):
file.write(self.q.get())
EDIT 2: The code is a Python Class that creates an audio file using an I2S microphone similar to the image shown in the question. While the value self.open is true, sounddevice will write the audio data into a queue (def callback) and then write the data into a file. All you have to do is toggle self.open to start and stop recording.
I'm playing a mp4 file in python, but the sound of the video doesn't comes out, I searched for a while if it's anyway to play the sound, but I could not find anything. Does anyone knows how to play the sound?
I post the code that displays de video :
import cv2
import numpy as np
# Create a VideoCapture object and read from input file
# If the input is the camera, pass 0 instead of the video file name
cap = cv2.VideoCapture('video.mp4')
# Check if camera opened successfully
#if (cap.isOpened()== False):
# print("Error opening video stream or file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame',frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()
It seems useless that OpenCV doesn't allow to play the sound. I'm using Python 3 by the way. Thank you.
ANSWER: OpenCV is a computer-vision library. It does not support audio. If you want to play sound, you can try ffpyplayer. – Thanks to >>> yushulx
You can use Pyglet to play video along with its audio....
Hope this helps...
import pyglet
vid_path='vid1.mp4' # Name of the video
window=pyglet.window.Window()
player = pyglet.media.Player()
source = pyglet.media.StreamingSource()
MediaLoad = pyglet.media.load(vid_path)
player.queue(MediaLoad)
player.play()
#window.event
def on_draw():
if player.source and player.source.video_format:
player.get_texture().blit(50,50)
pyglet.app.run()