Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Voice recorder and play sound
-
@mikael said:
but your code does not seem to do anything, as none of the functions get called.
I suppose that the def's are called by buttons in his View because they unique parameter is sender
-
@geniu Player(filename) loads the file when the Player is created. So it should be clear that, since your file has not yet been recorded, the player is loading the old file.
a better approach would be to set the play button disabled initially, and during the record function. then, enable it in stop_record. instantiate the Player as a local variable within the play button action, so it always reloads the file.
I am not sure we have the ability to easily control which speake is used, except by using an objc approach.
-
@mikael said:
@geniu, I might be mistaken, but your code does not seem to do anything, as none of the functions get called.
Regarding the external/device speaker, that is something I would change from device settings. Can you please explain a bit more?
Sorry I didn't explain it. As @cvp mentioned functions are called by buttons. I have 3 buttons: record, stop record and play.
Could you explain where is these settings? I cannot find it.
-
@JonB said:
@geniu Player(filename) loads the file when the Player is created. So it should be clear that, since your file has not yet been recorded, the player is loading the old file.
a better approach would be to set the play button disabled initially, and during the record function. then, enable it in stop_record. instantiate the Player as a local variable within the play button action, so it always reloads the file.
I am not sure we have the ability to easily control which speake is used, except by using an objc approach.
Thank you for explaining. Now it clear for me. I've tried to create Player in a play function firstly, but it doesn't seem to work. It plays nothing
-
@geniu said:
It plays nothing
Sure that your file exists and is not empty? Try it by tapping on it in the Pythonista files browser, then Quick Look, then the play button
-
One problem may be that you need to keep a reference to the player object, otherwise it is deleted as soon as the action returns.
Try creating a custom class to hold your button actions, or a custom view, then you can simply use self.player = sound.Player(file) and self.player.play() inside your action. Or, you could add an attribute to the button, using sender.
-
@cvp said:
@geniu said:
It plays nothing
Sure that your file exists and is not empty? Try it by tapping on it in the Pythonista files browser, then Quick Look, then the play button
Yes, I am. I can play it by Quick Look.
Andprint(os.listdir())
inside the play function shows that the file exists. And I can play it from console by creation a new Player instance -
-
@geniu something like
import sound from sound import Player import ui def play(sender): sender.player.play() v_str = ''' [ { "nodes" : [ { "nodes" : [ ], "frame" : "{{80, 104}, {80, 32}}", "class" : "Button", "attributes" : { "action" : "play", "frame" : "{{80, 104}, {80, 32}}", "title" : "Play", "uuid" : "1D1987D9-DAFA-4228-A0D4-CCDBE54B962B", "class" : "Button", "name" : "play_button", "font_size" : 15, "border_width" : 1 }, "selected" : true } ], "frame" : "{{0, 0}, {240, 240}}", "class" : "View", "attributes" : { "enabled" : true, "background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)", "tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)", "border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)", "flex" : "" }, "selected" : false } ] ''' v = ui.load_view_str(v_str) v['play_button'].player = Player('4.m4a') v.present('sheet')
-
@cvp said:
@geniu something like
import sound from sound import Player import ui def play(sender): sender.player.play() v_str = ''' [ { "nodes" : [ { "nodes" : [ ], "frame" : "{{80, 104}, {80, 32}}", "class" : "Button", "attributes" : { "action" : "play", "frame" : "{{80, 104}, {80, 32}}", "title" : "Play", "uuid" : "1D1987D9-DAFA-4228-A0D4-CCDBE54B962B", "class" : "Button", "name" : "play_button", "font_size" : 15, "border_width" : 1 }, "selected" : true } ], "frame" : "{{0, 0}, {240, 240}}", "class" : "View", "attributes" : { "enabled" : true, "background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)", "tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)", "border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)", "flex" : "" }, "selected" : false } ] ''' v = ui.load_view_str(v_str) v['play_button'].player = Player('4.m4a') v.present('sheet')
Thank you. I'll try and let you know if this works.
-
-
@geniu said:
Play still plays after reload app.
I have tested with a .m4a file of only one word, thus...
-
Here is my new code.
import ui from sound import Recorder from sound import Player class recorderView(ui.View): def __init__(self): self.file = '4.m4a' self.player = Player(self.file) self.recorder = Recorder(self.file) record_button = ui.ButtonItem() record_button.title = 'record' record_button.action = self.rec play_button = ui.ButtonItem() play_button.title = 'play' play_button.tint_color = 'red' play_button.action = self.play self.right_button_items = [record_button, play_button] def rec(self, sender): self.recorder.record(3) print(self.recorder.recording) def play(self, sender): print('before calling play method:', self.player.playing) self.player.play() print('after calling play method:', self.player.playing) v = recorderView() v.name = 'Recorder' v.present('sheet')
And here is the piece of play method’s code:
print('before calling play method:', self.player.playing) self.player.play() print('after calling play method:', self.player.playing)
After launch app if I firstly tap the play button sound is playing and output is:
before calling play method: False
after calling play method: TrueBut after recording sound is not playing although
player
exists.
Because I can get player’s attributes.
The output is:before calling play method: False
after calling play method: False -
see
https://gist.github.com/0a8414b4d0edc8a104136f5a88c0acc1
for a simple implementation using a custom View Class.If you want to use a custom view class with the ui designer, you need to specify the custom class name when you create the ui, then you dont need to create the buttons manually, but you would want to assign convience attributes and actions inside view_did_load... but i digress.
This could all be done using sender.superview to get to the root view, and just add custom attributes to the superview -- so no custom class, you would just replace self with sender.superview -- but a class makes everything much cleaner.
Here, i create the player as soon as the recording stops, rather than every play press -- that saves you from having to create a new Player every time. probably, you could create the Recorder once, in the init, but if you want to be able to change file name dynamically, you would create in the record callback as i did.
I got a little fancy, and turn the record/play into the stop button, and disable the other button while playing or recording, which eliminates the need for a third button.
One advantage of a custom class is you can define a custom update method, which in this case can display recorder/player times. you can also define a custom draw() method, which would let you show peak/average bars while recording.
-
@geniu your problem was that you were still creating the Player before the file was created.
think of sound.Player(file) as reading the file as soon as you create the Player... because that is exactly what it does, so it can precache the sound for efficiency.
so, you must create the player only after the recording stops.
if you are using record(3) to record 3 seconds, you'd need to use ui.delay to call another method that arms the player once recorder is done (unfortunately, record doesnt have a finish handler). or create it inside the play callback, just be sure to assign it to self.player so that the object doesnt get deleted while it is playing. -
@JonB, i appreciate your help. Thank you. I need some time to process your answer but now I think everything will be fine.