Python av play file in infinite loop - python

Using https://pypi.org/project/av/ trying to open file for infinite playback.
But the cycle ends with the last frame.
After searching and reading manuals, test code looks as follows:
(Note: these options are expected to be passed down to aiortc.contrib.media.MediaPlayer and work similarly):
import av
av.open(file="file.mp4", options={"fflags": "+genpts", "loop": "-1"})
for frame in media.decode():
print(frame)
Question: What should be the options (and if it is possible) to play file in infinite loop? (NOT just once)

According to the documentation, you create a MediaPlayer using the parameter loop=True
from aiortc.contrib.media import MediaPlayer
player = MediaPlayer(file="file.mp4", options={"fflags": "+genpts"}, loop=True)
You don't need to call PyAV yourself. It is done in MediaPlayer (see source code).

Related

Jupyter / Colab : Play sound with any error in any cell + Play sound after completing long running cells

Sometimes an error happens but I don't notice because I may be running multiple cells at once.
I'd like errors to play a sound.
In other words, play a sound when the execution fails, an Exception is raised, when execution errors are found, etc.
Many people would like long running cells to play a sound when completed.
COLAB
I mixed the solutions I found in some places 1 2 3 4
a) Create a global exception handler that beeps on errors
b) Create a simple function that you place at the end of the long-running cell (some other approaches on links)
You can change the sounds to anything you like.
Note: The sounds inside the Exception Handler and the beep_completed() are very different and with reason. The first is short and non-annoying and the second is long and pleasant (in case you are away from computer so you clearly hear that the task is completed). In any case you can replace them.
Note: There is a line that only applies to Colab. If you can provide the one for Jupyter I will gladly update the answer.
# This line is specific for Colab (please provide alternative for Jupyter)
from google.colab import output
from IPython.core.ultratb import AutoFormattedTB
# Catch any Exception, play error sound and re-raise the Exception
#-------------------------------------------------
# initialize the formatter for making the tracebacks into strings
itb = AutoFormattedTB(mode = 'Plain', tb_offset = 1)
# this function will be called on exceptions in any cell
def custom_exc(shell, etype, evalue, tb, tb_offset=None):
# still show the error within the notebook, don't just swallow it
shell.showtraceback((etype, evalue, tb), tb_offset=tb_offset)
# Play an audio beep. Any audio URL will do.
output.eval_js('new Audio("http://soundbible.com/grab.php?id=419&type=wav").play()')
# # grab the traceback and make it into a list of strings
# stb = itb.structured_traceback(etype, evalue, tb)
# sstb = itb.stb2text(stb)
# print (sstb) # <--- this is the variable with the traceback string
# print ("sending mail")
# send_mail_to_myself(sstb)
# this registers a custom exception handler for the whole current notebook
get_ipython().set_custom_exc((Exception,), custom_exc)
#------------------------------------------
# Function to play a sound (to put at the end of a long job)
def beep_completed():
#url_sound="http://soundbible.com/grab.php?id=1795&type=mp3";
output.eval_js('new Audio("http://soundbible.com/grab.php?id=1795&type=mp3").play()')
# Just play it with
beep_completed()
Jupyter
Comment out as needed. If you want to use a local file, you have to download it first and maybe adjust the path.
from IPython.display import Audio, display
# ----- error sound --------
def play_sound_error(self, etype, value, tb, tb_offset=None):
self.showtraceback((etype, value, tb), tb_offset=tb_offset)
v1="http://soundbible.com/grab.php?id=419&type=wav" # Short Error Beep sound
v2="https://wav-sounds.com/wp-content/uploads/2017/09/Various-02.wav" # Short Baby cry
display(Audio(url=v1, autoplay=True))
v1="../sound_error_beep.wav" # Short Error Beep sound
v2="../sound_baby_cry.wav" # Short Baby cry
display(Audio(filename=v1, autoplay=True))
# ----- atach it to all Exceptions
get_ipython().set_custom_exc((Exception,), play_sound_error)
# ----- success sound --------
def play_sound_success():
v1='http://soundbible.com/grab.php?id=1795&type=wav'
#display(Audio(url=v1, autoplay=True))
display(Audio(filename='../sound_success.wav', autoplay=True))
Since in my use cases, the set_custom_exc solution was not acceptable as it did override the previously established custom exceptions, I have created a small notification package that works for both regular scripts (using sys.excepthook) and jupyter notebooks (using post_run_cell).
Furthermore, since I did not like to have a Jingle Bell situation when the cells crash immediately, I have added a customizable minimum time interval based on either the total execution time (when in scripts) or the cell execution time (when in notebooks).
The package comes both as import oneliners such as:
import ringbell.auto
Which will play a sound if the execution takes more than a minute.
Or for immediate notification:
import ringbell.immediate
Or, for notifications exclusively on exceptions:
import ringbell.all_exceptions
You can also use it to play a sound whenever you like, by importing the RingBell class and going:
from ringbell import RingBell
RingBell(
sample = "microwave",
minimum_execution_time = 0,
verbose = True
)
You can get it from PyPi by running:
pip install ringbell

Playing audio in jupyter, in a for loop

I have a ton of training data I need annotated, in order to do so I need to listen through a bunch of sound snippets and note what I hear. I wrote a small script for this in a notebook.
My main issue is that IPython display dosent show in loops. As an example:
import numpy
import IPython.display as ipd
sr = 22050# sample rate
T = 2.0# seconds
t = numpy.linspace(0, T, int(T*sr), endpoint=False)# time variable
x = 0.5*numpy.sin(2*numpy.pi*440*t)
ipd.Audio(x, rate=sr)
will show up with an audio box, and I will be able to play the sine wave.
But trying to play anything in a for loop yields nothing (such as:)
for i in range(10000000):
x = 0.5*numpy.sin(i*numpy.pi*440*t)
ipd.Audio(x, rate=sr)
If anyone has a good solution for looping through (and listening) a bunch of audio files (one at a time, since I need to loop through potentially hundreds of thousands sound snippets), I would be very much appreciative!
To display the audio files within the for loop, you need to use IPython.display.display with the Audio object like so:
import numpy
import IPython.display as ipd
for i in range(10000000):
x = 0.5*numpy.sin(i*numpy.pi*440*t)
ipd.display(ipd.Audio(x, rate=sr))
my answer was deleted. but if you want a continuous loop you can use the method i described here https://stackoverflow.com/a/73425194/664456
which is a = Audio(...); a.autoplay_attr = lambda: 'autoplay="autoplay" loop="loop"'

Goto\Jump in Python

I'm coding a text game in python 3.4 and when I though about making a save game came the question:
How can I jump to the place that the player stopped?
I'm making a simple game, me and my friends, so I just wanna jump to a certain part of the code, and I can't do that without having to make around 15 copies of the code, so can I jump to a line?
You can do that using something like python-goto but this is a very bad idea.
In python, you don't have really any reason to do a goto.
A way better way would be to save the structure containing your data with something like pickle and loading it back when the user want to restart the game.
For instance:
import pickle
game_data = {'something': [1, 2, 3 ]}
pickle.dump(game_data, open('file.bin', 'wb')
Then, you can load the data back:
import pickle
game_data = pickle.load(open('file.bin', 'rb'))
There is no goto built into Python. There are ways to effectively 'halt' in a method by using yield and creating a generator, which is effectively how Python coroutines work (see the asyncio module) however this isn't really appropriate for your needs.
For saving game state, saving and serialising the state you need to resume the gameplay in a more general way is a much better idea. You could use pickle For this serialisation.
You need to consider the game-state as something that you can assign a value (or values) to. If this is a very simple text game, then the player will have a location, and that location will presumably be something you can "jump" to via use of a reference.
Let's say your code follows this pseudo-code pattern:
start
player_location = 0
print_start_game_text()
begin loop:
display_text_for_location[player_location]
display_options_for_location[player_location]
player_location = parse_player_response(response_options_for_location[player_location])
if isGameEndCondition(player_location):
break;
print_end_game_text()
end
This pattern would reference some data files that, for each location provided some collection such as 1, "you are in a room, doors are [E]ast and [W]est. You can [S]ave your game, or [L]oad a previously saved one", { "E" : 3, "W" : 2, "S" : "savegame", "L" : "loadgame" }
Then using a function to display some options, collecting the users response and parsing that data, returning a single value; the next location. You then have a new key to reference the next element in the data-file.
IF your game is as simple as this, then your save file need only contain a single reference, the player's location! Simple.
If you have objects that the player can manipulate, then you'll need to figure out a way to keep track of those, their locations, or state-values - it all depends on what your game does, and how it's played.
You should be thinking along these program vs data lines though, as it will make the game much easier to design, and later, extend, since all you'd have to do to create a new adventure, or level, is provide a new datafile.

What is the simplest way to get from MIDI to real audio coming out my speakers (sound synthesis) in Python?

I'm starting work on an app that will need to create sound from lots of pre-loaded ".mid" files.
I'm using Python and Kivy to create an app, as I have made an app already with these tools and they are the only code I know. The other app I made uses no sound whatsoever.
Naturally, I want to make sure that the code I write will work cross-platform.
Right now, I'm simply trying to prove that I can create any real sound from a midi note.
I took this code suggested from another answer to a similar question using FluidSynth and Mingus:
from mingus.midi import fluidsynth
fluidsynth.init('/usr/share/sounds/sf2/FluidR3_GM.sf2',"alsa")
fluidsynth.play_Note(64,0,100)
But I hear nothing and get this error:
fluidsynth: warning: Failed to pin the sample data to RAM; swapping is possible.
Why do I get this error, how do I fix it, and is this the simplest way or even right way?
I could be wrong but I don't think there is a "0" channel which is what you are passing as your second argument to .play_Note(). Try this:
fluidsynth.play_Note(64,1,100)
or (from some documentation)
from mingus.containers.note import Note
n = Note("C", 4)
n.channel = 1
n.velocity = 50
fluidSynth.play_Note(n)
UPDATE:
There are references to only channels 1-16 in the source code for that method with the default channel set to 1:
def play_Note(self, note, channel = 1, velocity = 100):
"""Plays a Note object on a channel[1-16] with a \
velocity[0-127]. You can either specify the velocity and channel \
here as arguments or you can set the Note.velocity and Note.channel \
attributes, which will take presedence over the function arguments."""
if hasattr(note, 'velocity'):
velocity = note.velocity
if hasattr(note, 'channel'):
channel = note.channel
self.fs.noteon(int(channel), int(note) + 12, int(velocity))
return True

Documentation on PyQt Phonon backend audio effect 'speed'

When I look at the output of the function
Phonon.BackendCapabilities.availableAudioEffects()
I get this as one of the options:
>>> speed_effect = Phonon.BackendCapabilities.availableAudioEffects()[3]
>>> speed_effect.name()
PyQt4.QtCore.QString(u'speed')
>>> speed_effect.__doc__
'Phonon.EffectDescription()\nPhonon.EffectDescription(int, dict-of-QByteArray-QVariant)\nPhonon.EffectDescription(Phonon.EffectDescription)'
I understand that I need to insert this effect into a path connecting to my audio source file, and that implementation won't be difficult. What I don't understand is how to access options or what the functionality of this 'speed' effect is. How do I access it through the Python interface? Can I specify a playback rate (like 2x, 4x, etc., for doubling or quadrupling the speed) as an option to this?
Well, not too many people were looking at this so I kept going and finally figured it out. Note that all of this is specific to my particular backend media player, gstreamer, for Phonon. If you have a different backend, you'll need to do some tinkering to see what effects you need to play around with.
The way this works is that you can see names and descriptions of your Phonon.Effect() options by calling the function
from PyQt4 import QtGui, QtCore
from PyQt4.phonon import Phonon
list_of_backend_audio_effects = Phonon.BackendCapabilities.availableAudioEffects()
After this, I figured out which of the available effects was the gstreamer option 'speed', by doing this:
list_of_effect_names = [str(elem.name()) for elem in list_of_backend_audio_effects]
for iter in range(len(list_of_effect_names)):
if list_of_effect_names[iter] == 'speed':
effect_index = iter
break
Finally, you need to actually edit the parameters, which has to be done by going through a data type called a QVariant. To double the speed of the audio, here's what I called:
speed_effect = Phonon.Effect(list_of_backend_audio_effects[effect_index])
speed_effect.setParameterValue(speed_effect.parameters()[0],QtCore.QVariant(str(2)))
In the first line, I create a new Phonon.Effect() which takes the effect description as an input (the things returned by the call the availableAudioEffects()). Then I set the parameter of this effect object (the first argument) to take the QVariant value '2' (the second argument). On my system, the default speed is '1', the min is '0.1' and the max is '40', which represents ranges of speeds between one-tenth and 40 times as fast as the regular audio file encodes.
I hope this helps some Python folks with gstreamer change speeds of audio.

Categories

Resources