Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Created a screen recording program for linux

  • 03-07-2015 11:22am
    #1
    Closed Accounts Posts: 431 ✭✭


    As above created a screen recording program for linux it requires gtk and ffmpeg for the final conversion to .mkv anyone want to test it out? You can download thy .py from here: https://gist.github.com/silageman/229bb270cfacb567d360

    Just install ffmpeg and place the quam.py in the video folder and cd to that folder and run the python script with "python quam.py"

    CTRL + C exits

    If you do decide to try it let me know how you get on and any problems with it.

    software is completely free no restrictions/license

    thanks for your time
    Eoin


Comments

  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    Nice!

    Some quick feedback: the framerate is all wrong. The time.sleep() function isn't the only thing delaying the loop; it takes time to capture and save the images.

    I've made a change to render the video at an average framerate that reflects the average time it takes to capture the frames, which makes the playback happen at about realtime from what I can see.

    I'd change other things, such as writing the jpegs somewhere like /tmp and accepting command-line arguments for filenames, but that's no big deal.
    # -*- coding: utf-8 -*-
    import gtk.gdk
    import time
    import os
    
    print "  ________ _______    _____    "
    print " / ____/  |  \__  \  /     \   "
    print "< <_|  |  |  // __ \|  Y Y  \  "
    print " \__   |____/(____  /__|_|  /  "
    print "    |__|          \/      \/   "
    print "    |__|          \/      \/   "
    print ""
    
    def main():
    
        i = -1
        speed = 25
     
        restart = raw_input("Start Recording?: y/n ")
        if restart == "no" or restart == "n":
             exit(0)
        if restart == "yes" or restart == "y":
             print "ok then"
        start_time = time.time()
    
        try:
            while (True):
                i += 1
                w = gtk.gdk.get_default_root_window()
                sz = w.get_size()
                time.sleep(1.0 / speed)
                print "FRAME: {} OK!".format(i)
                pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
                pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
                pb.save("image{:04d}.jpeg".format(i), "jpeg")
        except KeyboardInterrupt:
            frame_rate = i / (time.time() - start_time)
            os.system("ffmpeg -framerate {} -i image%04d.jpeg -codec copy output.mkv".format(frame_rate))
            os.system("find . -type f -iname \*.jpeg -delete")
            print "######## VIDEO READY ########"
    
    if __name__ == "__main__":
        main()
    


  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    That's weird: vBulletin mangled the code.

    I've attached my version as a text file.


  • Registered Users Posts: 13,985 ✭✭✭✭Johnboy1951


    oscarBravo wrote: »
    That's weird: vBulletin mangled the code.

    I've attached my version as a text file.

    Frame rate of this is 1.66666 according to VLC when the .mkv is played back.


  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    Frame rate of this is 1.66666 according to VLC when the .mkv is played back.

    6.3 here. What rate is yours captured at?


  • Registered Users Posts: 13,985 ✭✭✭✭Johnboy1951


    oscarBravo wrote: »
    6.3 here. What rate is yours captured at?

    1.6 as VLC reports :confused:
    Input #0, image2, from 'image%04d.jpeg':
      Duration: 00:00:11.46, start: 0.000000, bitrate: N/A
        Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 1680x1050 [SAR 1:1 DAR 8:5], 1.67 fps, 1.66 tbr, 1.66 tbn, 1.66 tbc
    


  • Advertisement
  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    One of the changes I'd make is to replace the sleep() value with one that's calculated from the required framerate and the time since the last frame was captured. Obviously that could only impose an upper limit on the framerate.


  • Registered Users Posts: 13,985 ✭✭✭✭Johnboy1951


    frame_rate = i    # / (time.time() - start_time)
    

    I left the frame rate as 'i' (commented out the division) and got much better results ..... about 31fps output.
    (Just to prove that this machine had no problems producing the higher frame rate ..... even though in this case it is not accurate of course)

    I think the whole speed/time/frame_rate relationship needs to be looked at.


    ..... but I am no coder ;)


  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    frame_rate = i    # / (time.time() - start_time)
    

    I left the frame rate as 'i' (commented out the division) and got much better results ..... about 31fps output.
    (Just to prove that this machine had no problems producing the higher frame rate ..... even though in this case it is not accurate of course)

    I think the whole speed/time/frame_rate relationship needs to be looked at.


    ..... but I am no coder ;)

    If you leave the framerate as "i", you'll (in theory) end up with a 1-second video. The -framerate option to ffmpeg specifies that number of frames per second, and "i" represents (approximately) the number of stills that have been captured.

    My code divides the number of frames by the number of seconds, which is pretty much exactly what "frames per second" means.


  • Closed Accounts Posts: 431 ✭✭whats newxt


    oscarBravo wrote: »
    If you leave the framerate as "i", you'll (in theory) end up with a 1-second video. The -framerate option to ffmpeg specifies that number of frames per second, and "i" represents (approximately) the number of stills that have been captured.

    My code divides the number of frames by the number of seconds, which is pretty much exactly what "frames per second" means.

    Thanks for your help. I can't for the life of me figure out how to record system audio with pulse audio using ffmpeg i can record the mic but not system audio?


  • Registered Users Posts: 13,985 ✭✭✭✭Johnboy1951


    Thanks for your help. I can't for the life of me figure out how to record system audio with pulse audio using ffmpeg i can record the mic but not system audio?

    Did you get the audio sorted?

    This might be of some interest ...... a simple recorder app using PulseAudio and Sox
    https://dl.dropboxusercontent.com/u/50217193/PulseAudioRecorder.sh


  • Advertisement
  • Registered Users Posts: 6,583 ✭✭✭10-10-20


    Hey - I gave it a go on Mint 17.2. I know zero about python.

    ffmpeg has been dropped from the package selection, so can't easily be installed. Apparently it's due back in the next release, but has been forked into a package called libav-tools (sudo apt-get install libav-tools).

    Anyhow, as a result, it drops out with an error once the script tries to convert the jpeg's into a video file.
    Just by installing avtools and replacing the command ffmpeg with avcom made it work.
    os.system("avconv -framerate 15 -i image%04d.jpeg -codec copy output.mkv")%i
    

    One thing which I noticed was that it doesn't capture the cursor position. Can that be added into it as an option? (Capture Cursor Y/N?)


  • Banned (with Prison Access) Posts: 963 ✭✭✭Labarbapostiza


    oscarBravo wrote: »
    # -*- coding: utf-8 -*-
        try:
            while (True):
                i += 1
                w = gtk.gdk.get_default_root_window()
                sz = w.get_size()
                time.sleep(1.0 / speed)
                print "FRAME: {} OK!".format(i)
                pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
                pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
                pb.save("image{:04d}.jpeg".format(i), "jpeg")
        
    

    Would it be better to launch this bit of code as an independent thread? And use the timer to launch each thread, leaving each thread to capture, compress and save each image, without a pause?.......pb.save looks like it has a lot of work to do....if it didn't have to do jpeg compression it would take less time......the images would take up more space though.

    I believe, theoretically (I'm saying theoretical because I don't know how to do this), the fastest and most efficient way to capture motion video, is compare two frames, and only save only what has changed (the unchanged pixels are then transparent). This is also the most efficient method of play back. If you think about it, it's an incredibly efficient method, each frame is an image of the changes, not a full image.


    I don't know if your code is already doing that. If the pixel buffer; pb, is only taking changes. But if it isn't, you might try comparing pb with the previous frame (changes), to create the frame image.


  • Technology & Internet Moderators Posts: 28,789 Mod ✭✭✭✭oscarBravo


    It's not my code (I just hacked on it a bit) but: you're right that efficient video compression just stores changes between frames. That's what the last step does: it takes the series of stills and feeds them to ffmpeg, which is very good at efficient compression.

    It would be interesting to time the jpeg compression to see how long it takes; it may indeed speed things up to store uncompressed pixmaps rather than individually compressed frames, and let ffmpeg do all the compression work.

    The threading idea is interesting too, although I suspect it wouldn't help much: Python isn't good at efficient multi-threading if the threads are processor-bound, because of the global interpreter lock.

    I've used multithreading for a Python application that had to do SNMP polling of eight thousand IP addresses, of which only a percentage would ever respond to the queries. Having parallel threads wait for the query results (or timeouts) was very efficient because the code was IO-bound.


  • Registered Users Posts: 6,176 ✭✭✭Ubbquittious


    oscarBravo wrote: »
    It's not my code (I just hacked on it a bit) but: you're right that efficient video compression just stores changes between frames. That's what the last step does: it takes the series of stills and feeds them to ffmpeg, which is very good at efficient compression.

    It would be interesting to time the jpeg compression to see how long it takes; it may indeed speed things up to store uncompressed pixmaps rather than individually compressed frames, and let ffmpeg do all the compression work.

    The threading idea is interesting too, although I suspect it wouldn't help much: Python isn't good at efficient multi-threading if the threads are processor-bound, because of the global interpreter lock.

    I've used multithreading for a Python application that had to do SNMP polling of eight thousand IP addresses, of which only a percentage would ever respond to the queries. Having parallel threads wait for the query results (or timeouts) was very efficient because the code was IO-bound.

    Nice work

    Maybe try using the multiprocessing module which supposed to bypass the GIL


Advertisement