omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    4
    18
    3750
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • geniu
      geniu last edited by

      Hi!

      I am trying write a simple recorder.
      After recording the Player.play doesn’t play file. It works only after reload app
      And secondly it plays from the inner speaker.
      How can I fix it?
      How can i change audio output from inner speaker to speaker phone and play recorded sound consistently after recording ?

      Here is my code:

      import sound
      from sound import Recorder
      from sound import Player
      sound.set_volume(1)
      recorder = Recorder('4.m4a')
      player = Player('4.m4a')
      
      
      def record(sender):
        global recorder
        recorder.record()
      
      def stop_record(sender):
        global recorder
        recorder.stop()
        
        
      def play(sender):
        global player
        player.play()
        
        
      v = ui.load_view()
      v.present('sheet')
      
      
      mikael JonB 2 Replies Last reply Reply Quote 0
      • mikael
        mikael @geniu last edited by

        @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?

        cvp geniu 2 Replies Last reply Reply Quote 0
        • cvp
          cvp @mikael last edited by cvp

          @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

          1 Reply Last reply Reply Quote 1
          • JonB
            JonB @geniu last edited by JonB

            @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.

            geniu 1 Reply Last reply Reply Quote 0
            • geniu
              geniu @mikael last edited by

              @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.

              1 Reply Last reply Reply Quote 0
              • geniu
                geniu @JonB last edited by

                @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

                cvp 1 Reply Last reply Reply Quote 0
                • cvp
                  cvp @geniu last edited by cvp

                  @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

                  geniu 1 Reply Last reply Reply Quote 0
                  • JonB
                    JonB last edited by

                    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.

                    1 Reply Last reply Reply Quote 0
                    • geniu
                      geniu @cvp last edited by

                      @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.
                      And print(os.listdir()) inside the play function shows that the file exists. And I can play it from console by creation a new Player instance

                      cvp 2 Replies Last reply Reply Quote 0
                      • cvp
                        cvp @geniu last edited by

                        @geniu ok, then follow @JonB 's advice

                        1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp @geniu last edited by

                          @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')
                          
                          geniu 1 Reply Last reply Reply Quote 0
                          • geniu
                            geniu @cvp last edited by

                            @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.

                            1 Reply Last reply Reply Quote 0
                            • geniu
                              geniu last edited by

                              @cvp this doesn't work. Play still plays after reload app.
                              @JonB, could you give an example how can I make a custom class?

                              cvp 1 Reply Last reply Reply Quote 0
                              • cvp
                                cvp @geniu last edited by

                                @geniu said:

                                Play still plays after reload app.

                                I have tested with a .m4a file of only one word, thus...

                                1 Reply Last reply Reply Quote 0
                                • geniu
                                  geniu last edited by

                                  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: True

                                  But 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

                                  JonB 1 Reply Last reply Reply Quote 0
                                  • JonB
                                    JonB last edited by

                                    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.

                                    1 Reply Last reply Reply Quote 1
                                    • JonB
                                      JonB @geniu last edited by

                                      @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.

                                      1 Reply Last reply Reply Quote 1
                                      • geniu
                                        geniu last edited by

                                        @JonB, i appreciate your help. Thank you. I need some time to process your answer but now I think everything will be fine.

                                        1 Reply Last reply Reply Quote 0
                                        • First post
                                          Last post
                                        Powered by NodeBB Forums | Contributors