mre / timelapse Goto Github PK
View Code? Open in Web Editor NEW๐ฌ Native macOS app for recording timelapse videos of your desktop.
Home Page: https://endler.dev/2020/timelapse/
License: Apache License 2.0
๐ฌ Native macOS app for recording timelapse videos of your desktop.
Home Page: https://endler.dev/2020/timelapse/
License: Apache License 2.0
macOS Catalina 10.15.5 (19F101), running Timelapse 1.0.1.
Tapping Start recording
doesn't do anything (no notification either).
Tapping Stop recording
also doesn't do anything (no notification, nothing saved anywhere).
The app also doesn't seem to request permission to access the filesystem, which might explain why nothing happens.
In #1 (comment), I mention that the output of this tool is currently hardcoded to output.mp4
. See
Line 21 in d9c15a0
Might be a nice exercise for new contributors.
Would be nice to have a basic travis config for this project, which would build the project on every pull request. That might form the basis for #4.
Tried to do a timelapse of my day at work, however, when I went off to a meeting and closed my laptop screen the recording did not resume when I logged back in.
Recording stops when computer locks. When logging back in, the screenshots stop occurring and when "Stop Recording" is selected from menubar, the app stops responding. No video is output as I have to force quit.
It would be great if we could support Python 3. In #7, @mepda mentioned some problems he encountered while trying it. This would be a great first issue for a new contributor.
The idea was to make the ./timelapse
folder a Python package I'm sure. But, __init.py__
is not the correct form.
It should be __init__.py
.
##Supporting Evidence
The Python documentation on packages
When my system goes suspend or black screen the timelapse stop of take screenshots
someone else had that problem ?
At the moment, we use a custom function to show a notification (e.g. when a recording was started or stopped). Here is the code:
https://github.com/mre/timelapse/blob/master/timelapse/notify.py
This has some limitations:
It would be nice if we could use a library for showing proper notification instead.
Not sure if there already exists a native Python library to do that on macOS.
Does anybody know of such a library? If not, we could build one based on the discussion here.
The ability to pause/resume the recording would be a fantastic solution to this.
Also, I second the idea of bundling ffmpeg or any other dependencies with the app.
Such a valuable, nifty app. Gets the job done. Kudos to everyone contributing on this project.
When I press "stop recording", the main thread calls '.join' on the recorder thread, which never returns, so then the encoder is never called to make the video.
This ugly hack is what I need to do to workaround this issue:
https://github.com/cmangla/timelapse/commit/98482c04de8f99654061577f943313770f586121
I did pip3 install -r <(cut -d= -f1 < requirements.txt )
, so I got the latest versions of the dependencies. I couldn't build the versions listed in requirements.txt.
maybe i didn't wait long enough, but after I hit stop recording the program hung here:
about to execute:
mencoder mf://*.png -mf type=png:w=800:h=600:fps=25 -ovc lavc -lavcopts vcodec=mpeg4 -oac copy -o output.avi
no output file, but all the screenshots are there and happy. any ideas?
awesome tool btw :) hope i can get it working
The app is eating away all my disk with PNG captures.
As I understand it uses ffmpeg
anyway, I wonder why you're not simply creating the video directly. E.g. https://gist.github.com/jcayzac/142da3cfa9b00a1d9af2f29260d45930
When launching the program for the first time since upgrading to macOS Ventura, I get a "Timelapse Error" screen with two options, to open Console.app or to quit the app. I'm not sure if this screen is from the OS, Python (?), or the app itself.
I don't have experience developing Mac apps, but the logs suggest something to do with an app sandbox?
Here are some log items from Console.app just before the error.
default 00:28:54.194498-0500 runningboardd Launch request for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)> is using uid 501 (divined from auid 501 euid 501)
default 00:28:54.195590-0500 runningboardd Acquiring assertion targeting app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)> from originator [osservice<com.apple.Spotlight(501)>:815] with description <RBSAssertionDescriptor| "LS launch org.pythonmac.unspecified.Timelapse" ID:189-815-196393 target:app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)> attributes:[
<RBSDomainAttribute| domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)">
]>
default 00:28:54.196005-0500 runningboardd Assertion 189-815-196393 (target:app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>) will be created as active
default 00:28:54.196321-0500 runningboardd Executing launch request for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)> (LS launch org.pythonmac.unspecified.Timelapse)
default 00:28:54.196398-0500 runningboardd Checking PreventLaunch: global:0 exPath:/Applications/Timelapse.app/Contents/MacOS/Timelapse predicates:(null)
default 00:28:54.196453-0500 runningboardd Creating and launching job for: app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>
default 00:28:54.196512-0500 runningboardd _mutateContextIfNeeded called for org.pythonmac.unspecified.Timelapse
default 00:28:54.196871-0500 runningboardd 'app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>' Constructed job description (context <RBSLaunchContext: 0x7f8f2ea733b0>):
<dictionary: 0x7f8f2eabd500> { count = 21, transaction: 0, voucher = 0x0, contents =
"Platform" => <int64: 0x28a99b08c5dedaf9>: 1
"ProcessType" => <string: 0x7f8f2ea6ef70> { length = 3, contents = "App" }
"EnableTransactions" => <bool: 0x7ff84ee041c0>: false
"_ManagedBy" => <string: 0x7f8f2ea4eb00> { length = 22, contents = "com.apple.runningboard" }
"CFBundleIdentifier" => <string: 0x7f8f2ea541e0> { length = 35, contents = "org.pythonmac.unspecified.Timelapse" }
"_ResourceCoalition" => <string: 0x7f8f2ea91220> { length = 75, contents = "app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>" }
"ThrottleInterval" => <int64: 0x28a99cf73a213af9>: 2147483647
"MachServices" => <dictionary: 0x7f8f2eab8910> { count = 0, transaction: 0, voucher = 0x0, contents =
}
"EnablePressuredExit" => <bool: 0x7ff84ee041c0>: false
"LimitLoadToSessionType" => <array: 0<โฆ>
default 00:28:54.225009-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Memory Limits: active 0 inactive 0
<private>
default 00:28:54.225106-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] This process will not be managed.
default 00:28:54.225141-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] HOME is <private>
default 00:28:54.225169-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] TMPDIR is <private>
default 00:28:54.225198-0500 runningboardd Now tracking process: [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068]
default 00:28:54.225433-0500 runningboardd Calculated state for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>: running-active (role: UserInteractive)
default 00:28:54.225791-0500 runningboardd Using default underlying assertion for app: [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068]
default 00:28:54.226315-0500 runningboardd Acquiring assertion targeting [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] from originator [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] with description <RBSAssertionDescriptor| "RB Underlying Assertion" ID:189-189-196394 target:36068 attributes:[
<RBSDomainAttribute| domain:"com.apple.underlying" name:"defaultUnderlyingAppAssertion" sourceEnvironment:"(null)">,
<RBSAcquisitionCompletionAttribute| policy:AfterApplication>
]>
default 00:28:54.226459-0500 runningboardd Assertion 189-189-196394 (target:[app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068]) will be created as active
default 00:28:54.226651-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring jetsam update because this process is not memory-managed
default 00:28:54.226681-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring suspend because this process is not lifecycle managed
default 00:28:54.226713-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Set darwin role to: UserInteractive
default 00:28:54.226742-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring GPU update because this process is not GPU managed
default 00:28:54.226797-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring memory limit update because this process is not memory-managed
default 00:28:54.227190-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] reported to RB as running
default 00:28:54.228213-0500 runningboardd Calculated state for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>: running-active (role: UserInteractive)
default 00:28:54.231102-0500 runningboardd Acquiring assertion targeting [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] from originator [osservice<com.apple.coreservices.launchservicesd>:137] with description <RBSAssertionDescriptor| "foregroundApp:36068" ID:189-137-196395 target:36068 attributes:[
<RBSDomainAttribute| domain:"com.apple.launchservicesd" name:"RoleUserInteractiveNonFocal" sourceEnvironment:"(null)">
]>
default 00:28:54.231326-0500 runningboardd Assertion 189-137-196395 (target:[app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068]) will be created as active
default 00:28:54.232362-0500 runningboardd Calculated state for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>: running-active (role: UserInteractive)
default 00:28:54.234340-0500 loginwindow -[PersistentAppsSupport applicationReady:] | App: Timelapse.app, ready, updating active tracking timer
default 00:28:54.233819-0500 runningboardd Invalidating assertion 189-815-196393 (target:app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>) from originator [osservice<com.apple.Spotlight(501)>:815]
default 00:28:54.232141-0500 Spotlight LAUNCH: 0x0-0x10c90c8 org.pythonmac.unspecified.Timelapse starting stopped process.
default 00:28:54.234411-0500 loginwindow -[ApplicationManager checkInAppContext:eventData:] | ApplicationManager: Checked in app : Timelapse.app
default 00:28:54.234947-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring jetsam update because this process is not memory-managed
default 00:28:54.235086-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring suspend because this process is not lifecycle managed
default 00:28:54.235318-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring GPU update because this process is not GPU managed
default 00:28:54.235704-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring memory limit update because this process is not memory-managed
default 00:28:54.235899-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring jetsam update because this process is not memory-managed
default 00:28:54.236013-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring suspend because this process is not lifecycle managed
default 00:28:54.236260-0500 runningboardd Successfully acquired underlying assertion for [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068]
default 00:28:54.236485-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring GPU update because this process is not GPU managed
default 00:28:54.236850-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring memory limit update because this process is not memory-managed
default 00:28:54.240998-0500 distnoted register name: com.apple.sharedfilelist.change object: com.apple.LSSharedFileList.ApplicationRecentDocuments/org.pythonmac.unspecified.timelapse token: 26100000044 pid: 1670
default 00:28:54.340289-0500 runningboardd Calculated state for app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>: running-active (role: UserInteractiveNonFocal)
default 00:28:54.340291-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring jetsam update because this process is not memory-managed
default 00:28:54.340401-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring suspend because this process is not lifecycle managed
default 00:28:54.340467-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Set darwin role to: UserInteractiveNonFocal
default 00:28:54.340678-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring GPU update because this process is not GPU managed
default 00:28:54.340991-0500 runningboardd [app<application.org.pythonmac.unspecified.Timelapse.33360934.33360938(501)>:36068] Ignoring memory limit update because this process is not memory-managed
error 00:28:55.494038-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/zlib.cpython-37m-darwin.so
error 00:28:55.494282-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_heapq.so
error 00:28:55.494385-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_ctypes.so
error 00:28:55.494478-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_struct.so
error 00:28:55.494745-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_posixsubprocess.so
error 00:28:55.494942-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/select.so
error 00:28:55.495079-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/math.so
error 00:28:55.495214-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/objc/_objc.so
error 00:28:55.495316-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_elementtree.so
error 00:28:55.495388-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/pyexpat.so
error 00:28:55.495579-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_bz2.so
error 00:28:55.495701-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_lzma.so
error 00:28:55.495855-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/grp.so
error 00:28:55.495990-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/binascii.so
error 00:28:55.496186-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_datetime.so
error 00:28:55.496417-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_hashlib.so
error 00:28:55.496601-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_blake2.so
error 00:28:55.496778-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_sha3.so
error 00:28:55.497003-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_bisect.so
error 00:28:55.497181-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_random.so
error 00:28:55.497313-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_socket.so
error 00:28:55.497458-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_opcode.so
error 00:28:55.497610-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/_pickle.so
error 00:28:55.497750-0500 kernel Sandbox: logd_helper(165) deny(1) file-read-data /Applications/Timelapse.app/Contents/Resources/lib/python3.7/lib-dynload/CoreFoundation/_inlines.so
default 00:28:55.943646-0500 Timelapse Timelapse Error
Many people don't know how to use the command-line. Nevertheless, they would still like to use this project for recording time-lapses. Would be nice if we made a runnable macOS app out of the code here. This way, people could simply start the application with a click and start recording.
Instructions here: https://py2app.readthedocs.io/en/latest/
Installed app by dragging to applications folder. Run app, menu shows up in menubar, toggle start recording, wait, stop recording. Nothing shows up in Movies dir, also no errors, no output at all.
I tried running this as a Python 3 and Python 2 program and got problems with both.
Here's the error for python3:
File "timelapse.py", line 8, in <module>
from encoder import Encoder # Creates timelapse video
File "/Users/hector/Desktop/practice/63-hacktoberfest/01-timelapse/timelapse/encoder.py", line 42
print "\n\nabout to execute:\n%s\n\n" % ' '.join(command)
^
SyntaxError: invalid syntax```
And here's the error message for python2:
```Traceback (most recent call last):
File "timelapse.py", line 33, in <module>
class Timelapse(NSObject):
File "timelapse.py", line 103, in Timelapse
@objc.python_method
AttributeError: 'module' object has no attribute 'python_method'```
Timelapse is finally mature enough to create a 1.0 version. It only took a decade. ๐
That's a major milestone so I was thinking about announcing it on Twitter, https://www.reddit.com/r/Python/ and https://news.ycombinator.com/show.
Planning to write a little blog post to celebrate this achievement.
If you want to help me with that, check out https://hackmd.io/gTiX8GjwRqaC3_CCQOn2Jw.
If you find any last-minute showstoppers, please mention them here or create a separate issue.
Thanks to all the contributors so far!
@seleregb
@cmangla
@ShaneCreedon
@orcutt989
@gkpln3
@abnerpc
@ShreyaPrabhu
@Kerl1310
Make sure to add your twitter/github handle to the Credits section of the document. ๐ ๐ท
At the moment we start ffmpeg
after we stopped taking screenshots. The video-creation process can take quite long (up to a few minutes) depending on the duration of the recording.
It would be great if we could stream the screenshots into ffmpeg
while we record.
The risk is that interrupting the recording (e.g. by locking the screen or hibernating the machine) could stop the ffmpeg
stream. Also there would be no recovery in case the computer crashes.
Maybe there is an elegant solution to that.
Best thing I came up with so far is to keep the screenshots as a backup. If the process crashes, the user could at least manually stitch together a timelapse. If the recording succeeds, we could clean up the screenshots afterwards.
Thoughts appreciated.
It would be great to be able to adjust the screenshot interval before starting a recording. I'll look into how that would get done from the menubar with py2app
the AppKit
and/or Foundation
librariesPyObjC
. Possibly a slider and/or second value input dialog once a menu option is selected?
Thank you for this simple yet incredibly useful app!
A simple setting which changed which part of the screen is going to be recorded could be implemented. I would like to have the 3 options that are offered by the native screen recording tool:
This repository is currently unmaintained.
We are looking for Python developers who would like to continue the project.
Please take a look at the other open issues to get an overview of what we'd need help with.
If you're interested, please reply here. We would really appreciate it. ๐
Maybe there is a way to detect if a user is on a dark theme on macOS and use a white icon accordingly?
Right now, the project has no tests at all. Would be nice to come up with a basic unit testing setup based on pytest (for example).
In Encoder, ffmpeg
might not be at the path we've hardcoded.
We should use types wherever we can to make refactoring easier. If someone wants to give it a try, please go ahead. I can provide support if needed. ๐
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.