sensible-cinema 0.9.3 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +7 -4
- data/README +42 -28
- data/Rakefile +1 -1
- data/TODO +53 -51
- data/VERSION +1 -1
- data/bin/sensible-cinema +30 -27
- data/lib/blanker.rb +3 -3
- data/lib/keyboard_input.rb +1 -1
- data/lib/ocr.rb +12 -9
- data/lib/overlayer.rb +17 -5
- data/lib/screen_tracker.rb +33 -22
- data/never_do +27 -0
- data/spec/images/{4.bmp → vlc_2_4.bmp} +0 -0
- data/spec/images/youtube_2_3.bmp +0 -0
- data/spec/images/youtube_light_0.bmp +0 -0
- data/spec/images/youtube_light_2_1.bmp +0 -0
- data/spec/images/youtube_light_2_3.bmp +0 -0
- data/spec/images/youtube_light_4.bmp +0 -0
- data/spec/images/youtube_light_4_3.bmp +0 -0
- data/spec/images/youtube_light_5.bmp +0 -0
- data/spec/images/youtube_light_5_0.bmp +0 -0
- data/spec/images/youtube_light_8.bmp +0 -0
- data/spec/images/youtube_light_9.bmp +0 -0
- data/spec/ocr.spec.rb +25 -12
- data/spec/screen_tracker.spec.rb +47 -15
- data/zamples/players/{how_to_create_a_new_player_description.txt → how_to_create_more.txt} +7 -0
- data/zamples/players/vlc/full_screened_total_length_over_an_hour.yml +3 -0
- data/zamples/players/vlc/{vlc_windows_total_length_over_an_hour.yml → windowed_total_length_over_an_hour.yml} +5 -1
- data/zamples/players/vlc/{non_full_screened_total_length_under_an_hour.yml → windowed_total_length_under_an_hour.yml} +3 -1
- data/zamples/players/youtube/full_screened_1024x768.yml +3 -0
- data/zamples/players/youtube/normal_in_youtube.com.yml +22 -0
- data/zamples/scene_lists/White Christmas.yml +15 -0
- data/zamples/scene_lists/all_dogs_go_to_heaven_dvd.yml +9 -0
- data/zamples/scene_lists/category descriptions.yml +6 -2
- data/zamples/scene_lists/{example_scene_list.yml → example_scene_descriptions_list.yml} +26 -24
- data/zamples/scene_lists/gummy_bear_song_youtube.yml +8 -7
- data/zamples/scene_lists/nuki_song_youtube.yml +9 -9
- metadata +24 -10
data/LICENSE
CHANGED
|
@@ -4,13 +4,16 @@ May contain some 3rd party libraries under their own (separate, open source) lic
|
|
|
4
4
|
|
|
5
5
|
Note that this software should be legal in the EU,
|
|
6
6
|
as it is only software and therefore theoretically not subject to patents (see "What about patent licenses?" in [2]).
|
|
7
|
-
|
|
7
|
+
It's basically for use in the EU.
|
|
8
8
|
If it's not legal in your country, don't use it!
|
|
9
9
|
|
|
10
|
-
http://en.wikipedia.org/wiki/Family_Entertainment_and_Copyright_Act describes a recent
|
|
11
|
-
in its favor.
|
|
10
|
+
The http://en.wikipedia.org/wiki/Family_Entertainment_and_Copyright_Act describes a recent
|
|
11
|
+
US law that appears related (and is in its favor).
|
|
12
|
+
|
|
13
|
+
A history of various related thoughts was described here:
|
|
14
|
+
http://betterlogic.com/roger/?p=2618
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
Enjoy!
|
|
14
17
|
|
|
15
18
|
[1] http://www.gnu.org/licenses/gpl.html, also gplv3 file.
|
|
16
19
|
[2] http://www.videolan.org/support/faq.html
|
data/README
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Sensible-cinema is a program that allows you to do pre-programmed scene selection (i.e. "mute out"
|
|
2
2
|
or "bleep out" scenes) on arbitrary media players like netflix online, vlc, etc.
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
Currently it takes as input a list of "skippable" scenes, and a player description.
|
|
6
5
|
It then tracks whichever player you are using, and mutes or blanks out the system appropriately,
|
|
7
6
|
during the scenes specified.
|
|
@@ -51,9 +50,9 @@ To program sensible-cinema, you create a scene description list it can use.
|
|
|
51
50
|
|
|
52
51
|
An Edit Decision List (EDL) looks something like this trivial example:
|
|
53
52
|
|
|
54
|
-
mutes:
|
|
55
|
-
"01:00:00" : "01:01:02.5" # mute from exactly one hour to one hour, one minute, two seconds and a half will be muted.
|
|
56
|
-
blank_outs:
|
|
53
|
+
mutes:
|
|
54
|
+
"01:00:00" : "01:01:02.5" # mute from exactly one hour to one hour, one minute, two seconds and a half will be muted.
|
|
55
|
+
blank_outs:
|
|
57
56
|
"01:00:00" : "01:01:02.5" # also blank out (overlay with blank window) the same.
|
|
58
57
|
|
|
59
58
|
Here's one with more detail
|
|
@@ -89,35 +88,34 @@ This will create the file "example_scene_list Copy.yml"
|
|
|
89
88
|
Right click on it, choose rename, and give it a better name.
|
|
90
89
|
Now "right click -> Open" to open it in an editor (recommend installing notepad++ and using that).
|
|
91
90
|
|
|
92
|
-
== FAQ ==
|
|
93
|
-
|
|
94
|
-
Q. Can I watch movies this way on my TV, not just on my computer?
|
|
95
|
-
|
|
96
|
-
A.
|
|
97
|
-
|
|
98
|
-
(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
== FAQ ==
|
|
92
|
+
|
|
93
|
+
Q. Can I watch movies this way on my TV, not just on my computer?
|
|
94
|
+
|
|
95
|
+
A. Maybe. Or possible not yet, depending on your current hardware.
|
|
96
|
+
Currently you'll either need to attach your computer to your TV
|
|
97
|
+
(buy some long cables, or a new graphics card that matches your cables, etc.)
|
|
98
|
+
or get some computer that you can move closer to the TV to do the same
|
|
99
|
+
(ex: buy a used older laptop with s-video out, use that, or a laptop with DVI/HDMI would
|
|
100
|
+
work with an HDMI TV). If you're really aggressive you could run an ethernet cable from your computer, as well [1].
|
|
101
|
+
I'd be happy to do a linux port of sensible-cinema if anybody requests it, for use with
|
|
102
|
+
their dedicated TV computer.
|
|
103
|
+
There has also been some work toward getting ones computer to stream "live" to your existing wii/ps3/xbox.
|
|
104
|
+
Message me if you're interested in trying it out (testers wanted--plus I'll only work on it if there's demand)!
|
|
103
105
|
|
|
104
106
|
Q. What movies does this work with?
|
|
105
107
|
|
|
106
|
-
A. Any that you program it for :) (Assuming the player is compatible, which most probably are.)
|
|
108
|
+
A. Any that you program it for :) (Assuming the computer player is compatible, which most probably are.)
|
|
107
109
|
|
|
108
110
|
Q. What movies are freely available to watch online?
|
|
109
111
|
|
|
110
|
-
A. Not many are available free (hulu, youtube have a few)
|
|
111
|
-
|
|
112
|
+
A. Not many are available free (hulu, youtube have a few). Netflix has quite a few with its default subscription.
|
|
113
|
+
You can of course use it with any existing DVD, or rent or borrow DVD's and watch them using sensible-cinema.
|
|
112
114
|
|
|
113
115
|
Q. Why does my mouse bounce up and down while sensible-cinema is going?
|
|
114
116
|
|
|
115
117
|
A. This enables your player to keep its on-screen time tracker, which in turn allows sensible-cinema to track where
|
|
116
|
-
you're at. Message me if this bugs you too much and we'll see what we can do
|
|
117
|
-
|
|
118
|
-
Q. Why does it seem really laggy at time detection at the beginning?
|
|
119
|
-
|
|
120
|
-
A. It takes it awhile to warm up its digit detection. Ping me if you would like to see this improved speed-wise.
|
|
118
|
+
you're at. Message me if this bugs you too much and we'll see what we can do about it.
|
|
121
119
|
|
|
122
120
|
[1] http://ps3mediaserver.org/forum/viewtopic.php?f=6&t=5731#p34279
|
|
123
121
|
|
|
@@ -131,6 +129,15 @@ to pick them each time, like:
|
|
|
131
129
|
Also if you specify "test" for the scene descriptions file, it will pause 4s, take a snapshot of the player, then exit.
|
|
132
130
|
You can also specify -v or -t if you want to enable more verbose (chatty) output.
|
|
133
131
|
|
|
132
|
+
== Caveats ==
|
|
133
|
+
|
|
134
|
+
NB that "someone" will have to create a scene descriptions list, per DVD/online movie.
|
|
135
|
+
Unless it already exists, then "someone" already did.
|
|
136
|
+
|
|
137
|
+
Also note that it takes a bit to get "warmed" up when you first start using it (it uses OCR
|
|
138
|
+
to track the screen time), so it might be a tidge laggy at time tracking when first used.
|
|
139
|
+
Ping me if you want this improved.
|
|
140
|
+
|
|
134
141
|
== Thanks ==
|
|
135
142
|
|
|
136
143
|
Thanks to Jarmo for the win32-screenshot gem, mini_magick gem authors, jruby guys, etc.
|
|
@@ -142,15 +149,22 @@ See the LICENSE file for licensing, usage terms (basically gplv3).
|
|
|
142
149
|
|
|
143
150
|
== Related ==
|
|
144
151
|
|
|
152
|
+
http://imdb.com tends to have reasonably good lists of what occurs in movies (find a movie, click on "parent's guide" on the left).
|
|
153
|
+
Sometimes it even lists the time signatures for events (ex: "Labyrinth" http://www.imdb.com/title/tt0047673/parentalguide)
|
|
154
|
+
which you could use to translate into a sensible-cinema compatible list.
|
|
155
|
+
|
|
145
156
|
The concept isn't too novel:
|
|
146
157
|
|
|
147
|
-
http://en.wikipedia.org/wiki/Edit_decision_list (linear editing tool)
|
|
148
|
-
http://www.imdb.com/swiki/special?ParentalGuideHelp search for "scene description"
|
|
158
|
+
http://en.wikipedia.org/wiki/Edit_decision_list (it's linear editing tool)
|
|
159
|
+
http://www.imdb.com/swiki/special?ParentalGuideHelp and search for "scene description"
|
|
149
160
|
http://www.oreillynet.com/sysadmin/blog/2005/06/make_your_own_phantom_edit_wit.html
|
|
161
|
+
http://forum.bsplayer.com/feature-requests-feedback-suggestions/7157-chapter-playlist-scene-cut-3.html
|
|
162
|
+
http://www.inmatrix.com/ "scene cut editor" of the zoom player
|
|
163
|
+
http://wiki.xbmc.org/?title=EDL_(commercial_skipping)_and_SceneMarker_support (XBMC's scene cut support--also links to more others)
|
|
164
|
+
http://code.google.com/p/movie-content-editor (same thing, but in Python and only for VLC)
|
|
165
|
+
http://clearplay.com similar, but commercial (closed), and only for DVD's (has its own DVD-player)
|
|
150
166
|
|
|
151
|
-
|
|
152
|
-
Sometimes it even lists the time signatures for events (ex: "Labyrinth" http://www.imdb.com/title/tt0047673/parentalguide)
|
|
153
|
-
which you could use to translate into a sensible-cinema compatible list.
|
|
167
|
+
though none of them are universal like this one is :)
|
|
154
168
|
|
|
155
169
|
== Feedback ==
|
|
156
170
|
|
data/Rakefile
CHANGED
|
@@ -7,7 +7,7 @@ Jeweler::Tasks.new do |s|
|
|
|
7
7
|
s.homepage = "http://github.com/rdp"
|
|
8
8
|
s.authors = ["Roger Pack"]
|
|
9
9
|
s.add_dependency 'sane', '>= 0.22.0'
|
|
10
|
-
s.add_dependency 'rdp-win32screenshot', '>= 0.0.
|
|
10
|
+
s.add_dependency 'rdp-win32screenshot', '>= 0.0.7.3'
|
|
11
11
|
s.add_dependency 'mini_magick' # for ocr...
|
|
12
12
|
s.add_development_dependency 'rspec' # prefer rspec 2 I guess...
|
|
13
13
|
s.add_development_dependency 'jeweler'
|
data/TODO
CHANGED
|
@@ -1,73 +1,77 @@
|
|
|
1
1
|
== medium ==
|
|
2
2
|
|
|
3
|
+
make all players actually play again
|
|
4
|
+
|
|
3
5
|
== low but actually want to do eventually (me) low prio: just do these...==
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
youtube non full screen: work with other browsers
|
|
8
|
+
slightly more accurate timestamp...
|
|
9
|
+
can parse IMDB (require they put in the URL by hand)
|
|
10
|
+
try the new GOCR sources...
|
|
11
|
+
PISH
|
|
12
|
+
add stuffs to imdb
|
|
6
13
|
|
|
7
14
|
== random backlog ... based on user request..remember: just local files for my own needs...==
|
|
8
|
-
note: just plow forward, to "grab" available ideas...
|
|
9
|
-
except that for now, just what *I* plan on needing for myself.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
note: just plow forward, to "grab" available ideas...except that for now, just what *I*
|
|
17
|
+
plan on needing for myself (filters for what I need/want).
|
|
18
|
+
|
|
19
|
+
re-advertise on ruby talk
|
|
20
|
+
|
|
21
|
+
no money making for now...all volunteer...
|
|
22
|
+
|
|
23
|
+
an "online anybody can chat while watching this movie" (or anybody can edit this wav and listen to it a overlay...)
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
an online applet web runnable? Why not?
|
|
26
|
+
click here to watch your favorite film edited! Just click! [* yea!]
|
|
27
|
+
a chrome plugin with imdb/community backing :)
|
|
14
28
|
|
|
15
|
-
|
|
29
|
+
code refactors: "screen time change", order should be swapped in bin/x output
|
|
30
|
+
|
|
31
|
+
auto-play on detect youtube url access...
|
|
16
32
|
|
|
17
33
|
easier installer for windows: release a zip file that they can just click on a .bat file to run it
|
|
18
34
|
later: it installs/uninstalls appropo
|
|
19
35
|
suggestion: self-extractor
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
make it able to use multiple players so I can maximize VLC...
|
|
37
|
+
make it able to use both windowed and maximized VLC (and full screen) seamlessly
|
|
24
38
|
|
|
25
|
-
blank overlay text like "and you are one awesome klingon"
|
|
39
|
+
can blank overlay with text like "and you are one awesome klingon"
|
|
26
40
|
|
|
27
41
|
screencast of things helpful (use, creation).
|
|
28
42
|
|
|
29
|
-
TSR that monitors "oh you're opening a VLC? you're playing the E drive? That's bob's big plan? You're maximized? Full screened? watching x on hulu?"
|
|
43
|
+
TSR that monitors "oh you're opening a VLC? you're playing the E drive? That's bob's big plan? You're maximized? Full screened? watching x on hulu? y on youtube?"
|
|
30
44
|
|
|
31
|
-
a netflix online player
|
|
45
|
+
a netflix online player descriptor
|
|
32
46
|
|
|
33
|
-
add my stuff to imdb
|
|
47
|
+
add my stuff to imdb...?
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
make youtube work if you have *several* open
|
|
36
50
|
|
|
37
51
|
user customizable levels...
|
|
38
52
|
maybe even "I don't like ones that are x, y, z", or "boring level x"
|
|
39
53
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
can overlay with a "fuzzer-outer" for specific coordinates somehow or other...
|
|
54
|
+
with VLC/youtube non full screen, it does the annoying mouse thing needlessly (which doesn't bug as much these days...)
|
|
43
55
|
|
|
44
|
-
|
|
56
|
+
hulu non full screened descriptor
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
can overlay with wav file (would work already for VLC [?], could also "click to mute" for others...hmm...)
|
|
47
59
|
|
|
48
|
-
|
|
60
|
+
fix any/all pending tests...
|
|
49
61
|
|
|
50
|
-
|
|
62
|
+
can permanently black out certain coords to keep things prettier...
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
can black out certain coords to keep things prettier...
|
|
55
|
-
|
|
56
|
-
allow x2,y2 for player descriptions...
|
|
57
|
-
|
|
58
|
-
Linux port (call that good enough for usability on TV's...) between that and a VLC version...
|
|
59
|
-
|
|
60
|
-
a web runnable? Why not?
|
|
61
|
-
click here to watch your favorite film edited! Just click!
|
|
64
|
+
Linux port (call that good enough for usability on TV's...), should be...
|
|
62
65
|
|
|
63
66
|
blank out with specifiable color
|
|
64
67
|
better default color?
|
|
65
68
|
|
|
66
69
|
Auto mute/blank commercials?
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
transfer ownership to an LLC
|
|
72
|
+
new github username
|
|
69
73
|
|
|
70
|
-
replay
|
|
74
|
+
replay certain film sections :P
|
|
71
75
|
|
|
72
76
|
overlay/replace current playback with some url of audio or video
|
|
73
77
|
user editable overlays (like a wiki...)
|
|
@@ -76,34 +80,32 @@ control volume programmatically (using mouse) on the player itself.
|
|
|
76
80
|
control mute programmatically (using mouse) on the player itself.
|
|
77
81
|
control location programmatically (using mouse) on the player itself.
|
|
78
82
|
|
|
79
|
-
compare timings with a real DVD player...
|
|
83
|
+
compare VLC (and other) timings with a real DVD player...
|
|
80
84
|
|
|
81
85
|
overlay with an alpha transparent pic
|
|
82
86
|
|
|
83
87
|
Have a "list of all known movies (url's)" and be able to open (IE et al) to the correct part, and start playing them, and they work...
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
does my sweet heart have any suggestions? (make it work well for laymen)
|
|
86
90
|
|
|
87
|
-
|
|
91
|
+
some type of installer that can setup the registry...
|
|
88
92
|
|
|
89
93
|
auto-assignment of EDL's to media:
|
|
94
|
+
auto-play option for DVD's (auto-start?)
|
|
95
|
+
use normal differentiation
|
|
96
|
+
use spiffy differentiation for DVD's on windows
|
|
90
97
|
DVD's (right click on DVD player, play with scene-skipper?)
|
|
91
98
|
web browser plugin?
|
|
92
|
-
auto start on DVD insertion (?)
|
|
93
|
-
and show appropriate scene-lists available based on title/md5 of something?
|
|
94
99
|
|
|
95
|
-
Programmatically do all of the above, by driving
|
|
100
|
+
Programmatically do all of the above, by driving VLC with its real API.
|
|
96
101
|
VLC
|
|
97
|
-
Allow it to record
|
|
102
|
+
Allow it to record somehow (recordable)
|
|
98
103
|
burnable to DVD/CD ...
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
For now it's either a cable, a computer (with its cable), or pay.
|
|
108
|
-
todo: make a VLC wrapper so it works *if your soundcard supports it*
|
|
109
|
-
after: make the same work awesome on doze 7 without soundcard support :)
|
|
104
|
+
use VLC's web interface? telnet?
|
|
105
|
+
optimize it with best appropriate iframes (LOL)
|
|
106
|
+
|
|
107
|
+
star trek: generations first profanidade...
|
|
108
|
+
|
|
109
|
+
"Showing EDL Information During Playback"
|
|
110
|
+
|
|
111
|
+
integrate with google TV/bravia...maybe...somehow...boxxee?
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.4
|
data/bin/sensible-cinema
CHANGED
|
@@ -4,12 +4,16 @@ require 'sane'
|
|
|
4
4
|
|
|
5
5
|
Thread.abort_on_exception=true #gah
|
|
6
6
|
|
|
7
|
-
for file in ['overlayer', 'keyboard_input', 'screen_tracker', 'mouse', 'file_chooser']
|
|
7
|
+
for file in ['overlayer', 'keyboard_input', 'screen_tracker', 'mouse', 'file_chooser', 'ocr']
|
|
8
8
|
require_relative '../lib/' + file
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
$VERBOSE = 1 if ARGV.delete('-v')
|
|
12
12
|
$TEST = 1 if ARGV.delete('-t')
|
|
13
|
+
if ARGV.delete('--clear-cache')
|
|
14
|
+
OCR.clear_cache!
|
|
15
|
+
puts 'cleared cache'
|
|
16
|
+
end
|
|
13
17
|
|
|
14
18
|
$stderr.puts 'warning: currently windows only for certain parts currently' unless ENV['OS'] == 'Windows_NT'
|
|
15
19
|
|
|
@@ -17,63 +21,59 @@ if ARGV.detect{|arg| arg == '-h' || arg == '--help'}
|
|
|
17
21
|
|
|
18
22
|
puts <<-END
|
|
19
23
|
|
|
20
|
-
syntax:
|
|
24
|
+
syntax: player_description.yml|test scene_descriptions_list.yml [-t -v --clear-cache] (or nothing to prompt for files)
|
|
21
25
|
END
|
|
22
26
|
|
|
23
27
|
for file in Dir[__dir__ + '../zamples/mute*/*']
|
|
24
28
|
puts "\n", "Example file:", file + "\n\n", File.read(file)
|
|
25
29
|
end
|
|
26
30
|
|
|
27
|
-
puts '', 'Available files:'
|
|
28
|
-
for file in Dir[__dir__ + '../zamples/*/*']
|
|
29
|
-
puts File.expand_path(file) unless File.directory?(file)
|
|
30
|
-
end
|
|
31
31
|
exit 1
|
|
32
32
|
|
|
33
33
|
else
|
|
34
34
|
|
|
35
35
|
# allow for command line filenames
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
|
|
37
|
+
player_description = ARGV.shift.to_s
|
|
38
|
+
if !File.exist?(player_description)
|
|
39
|
+
puts 'Please Select Computer Player'
|
|
40
|
+
player_description = FileChooser.choose_file("SELECT COMPUTER PLAYER", __dir__ + "/../zamples/players")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
scene_list = ARGV.shift.to_s
|
|
38
44
|
|
|
39
45
|
if scene_list == 'test'
|
|
40
46
|
overlay = nil
|
|
41
47
|
p 'got test...just doing screen dump'
|
|
42
|
-
$VERBOSE=true # some extra output
|
|
48
|
+
$VERBOSE=true # adds some extra output
|
|
43
49
|
else
|
|
44
|
-
if !File.exist? scene_list
|
|
50
|
+
if !File.exist? scene_list
|
|
45
51
|
puts 'Select Scene Descriptions file'
|
|
46
52
|
scene_list = FileChooser.choose_file("SELECT SCENE DESCRIPTIONS FILE", __dir__ + "/../zamples/scene_lists")
|
|
47
53
|
end
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
if !scene_list
|
|
50
56
|
puts "error: have to specify a scene descriptions file\n or specify \"test\" on the command line if you just want to snapshot your player"
|
|
51
57
|
exit 1
|
|
52
58
|
end
|
|
53
|
-
puts 'Selected scene descriptions file ' + File.basename(scene_list) + "\n\t(#{scene_list})"
|
|
54
|
-
Blanker.startup
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
player_description = FileChooser.choose_file("SELECT COMPUTER PLAYER", __dir__ + "/../zamples/players")
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# start it late as it has an annoying startup blip
|
|
65
|
-
overlay = OverLayer.new(scene_list)
|
|
60
|
+
puts 'Selected scene descriptions file ' + File.basename(scene_list) + "\n\t(full path: #{scene_list})"
|
|
61
|
+
Blanker.startup
|
|
62
|
+
# todo start it late as it has an annoying startup blip
|
|
63
|
+
overlay = OverLayer.new(scene_list)
|
|
64
|
+
end
|
|
66
65
|
|
|
67
66
|
if File.exist? player_description.to_s
|
|
68
|
-
puts 'Selected player ' + File.basename(player_description) + "\n\t(#{player_description})"
|
|
67
|
+
puts 'Selected player ' + File.basename(player_description) + "\n\t(full path: #{player_description})"
|
|
69
68
|
# this one doesn't use any updates, so just pass in file contents, not filename
|
|
70
69
|
screen_tracker = ScreenTracker.new_from_yaml File.binread(player_description), overlay
|
|
71
70
|
Mouse.jitter_forever_in_own_thread # when this ends you know the snapshot was taken...
|
|
72
71
|
|
|
73
72
|
# exit early if we just wanted a screen dump...a little kludgey...
|
|
74
73
|
unless overlay
|
|
75
|
-
puts 'warning--only doing screen dump in
|
|
74
|
+
puts 'warning--only doing screen dump in t-minus 4s...'
|
|
76
75
|
sleep 4
|
|
76
|
+
puts 'snap!'
|
|
77
77
|
screen_tracker.dump_bmp
|
|
78
78
|
exit 1
|
|
79
79
|
end
|
|
@@ -81,14 +81,17 @@ else
|
|
|
81
81
|
else
|
|
82
82
|
puts 'warning--not using any screen tracking...'
|
|
83
83
|
end
|
|
84
|
+
|
|
84
85
|
OCR.unserialize_cache_from_disk # do this every time so we don't delete it if they don't have one...
|
|
85
86
|
|
|
86
87
|
puts "Opening the curtains... (please play in player now)"
|
|
87
88
|
overlay.start_thread true
|
|
88
89
|
key_input = KeyboardInput.new overlay
|
|
89
90
|
key_input.start_thread # status thread
|
|
91
|
+
at_exit {
|
|
92
|
+
Blanker.shutdown # lodo move this and the 'q' key to within overlayer
|
|
93
|
+
OCR.serialize_cache_to_disk
|
|
94
|
+
}
|
|
90
95
|
key_input.handle_keystrokes_forever # when this method exits, we want to exit fully...
|
|
91
|
-
Blanker.shutdown # lodo move this and the 'q' key to within overlayer
|
|
92
|
-
OCR.serialize_cache_to_disk
|
|
93
96
|
|
|
94
97
|
end
|
data/lib/blanker.rb
CHANGED
|
@@ -9,11 +9,11 @@ else
|
|
|
9
9
|
JLabel = javax.swing.JLabel
|
|
10
10
|
|
|
11
11
|
def self.startup
|
|
12
|
-
@fr = JFrame.new("
|
|
12
|
+
@fr = JFrame.new("Sensible Cinema blanker-outer overlay window")
|
|
13
13
|
@fr.default_close_operation = JFrame::EXIT_ON_CLOSE
|
|
14
|
-
@fr.set_size(2000, 2000) # ltodo better size
|
|
14
|
+
@fr.set_size(2000, 2000) # ltodo better size ?
|
|
15
15
|
|
|
16
|
-
@label = JLabel.new
|
|
16
|
+
@label = JLabel.new
|
|
17
17
|
@fr.add(@label)
|
|
18
18
|
@label.repaint
|
|
19
19
|
@label.revalidate
|
data/lib/keyboard_input.rb
CHANGED
|
@@ -31,7 +31,7 @@ class KeyboardInput
|
|
|
31
31
|
def handle_keystrokes_forever
|
|
32
32
|
raise 'only jruby supported, as it looks just too messy in normal ruby' unless OS.java?
|
|
33
33
|
while(ch = getch)
|
|
34
|
-
|
|
34
|
+
exit if ch == 3 # ctrl+c
|
|
35
35
|
# lodo handle arrow keys, too, which is a bit more complicated...
|
|
36
36
|
handle_keystroke ch
|
|
37
37
|
end
|
data/lib/ocr.rb
CHANGED
|
@@ -10,10 +10,12 @@ module OCR
|
|
|
10
10
|
|
|
11
11
|
# options are :might_be_colon, :should_invert
|
|
12
12
|
def identify_digit memory_bitmap, options = {}
|
|
13
|
-
require 'mini_magick' # installation woe, but actually
|
|
13
|
+
require 'mini_magick' # here because of installation woe, but actually not a big slowdown
|
|
14
14
|
|
|
15
15
|
if CACHE.has_key?(memory_bitmap)
|
|
16
16
|
return CACHE[memory_bitmap] unless (defined?($OCR_NO_CACHE) && $OCR_NO_CACHE)
|
|
17
|
+
else
|
|
18
|
+
puts 'cache miss' if $DEBUG && $VERBOSE
|
|
17
19
|
end
|
|
18
20
|
if options[:might_be_colon]
|
|
19
21
|
# do processing in-line <sigh>
|
|
@@ -31,24 +33,25 @@ module OCR
|
|
|
31
33
|
# but doesn't want sharpen, for whatever reason...
|
|
32
34
|
# mogrify calls it negate...
|
|
33
35
|
image.negate
|
|
34
|
-
else
|
|
35
|
-
# youtube wants sharpen...
|
|
36
|
-
image.sharpen(2)
|
|
37
36
|
end
|
|
38
37
|
|
|
39
38
|
image.format(:pnm)
|
|
40
|
-
|
|
39
|
+
image.sharpen(2) if options[:sharpen] # hulu does *not* want sharpen, though I haven't checked it too closely...
|
|
40
|
+
|
|
41
|
+
previous = nil
|
|
42
|
+
p options if $DEBUG
|
|
43
|
+
for level in options[:levels]
|
|
41
44
|
a = `#{GOCR} -l #{level} #{image.path} 2>NUL`
|
|
42
|
-
# a can be like "_1_\n"
|
|
43
45
|
if a =~ /[0-9]/
|
|
46
|
+
# it can be like "_1_\n"
|
|
44
47
|
a.strip!
|
|
45
48
|
a.gsub!('_', '')
|
|
46
49
|
a = a.to_i
|
|
47
|
-
CACHE[memory_bitmap] = a
|
|
48
|
-
return a
|
|
50
|
+
return CACHE[memory_bitmap] = a
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
|
-
#
|
|
53
|
+
# cache failures here, for VLC's hour clock' sake
|
|
54
|
+
CACHE[memory_bitmap] = nil
|
|
52
55
|
nil
|
|
53
56
|
end
|
|
54
57
|
|
data/lib/overlayer.rb
CHANGED
|
@@ -40,6 +40,7 @@ class OverLayer
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def unblank!
|
|
43
|
+
@just_unblanked = true
|
|
43
44
|
@am_blanked = false
|
|
44
45
|
Blanker.unblank_full_screen!
|
|
45
46
|
end
|
|
@@ -89,6 +90,7 @@ class OverLayer
|
|
|
89
90
|
@cv = ConditionVariable.new
|
|
90
91
|
@file_mtime = nil
|
|
91
92
|
check_reload_yaml
|
|
93
|
+
@just_unblanked = false
|
|
92
94
|
@start_time = Time.now_f # assume they want to start immediately...
|
|
93
95
|
end
|
|
94
96
|
|
|
@@ -145,7 +147,14 @@ class OverLayer
|
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
def timestamp_changed to_this_exact_string_might_be_nil, delta
|
|
148
|
-
|
|
150
|
+
if @just_unblanked
|
|
151
|
+
# ignore it, since it was probably just caused by the screen blipping
|
|
152
|
+
# at worse this will put us 1s behind...hmm.
|
|
153
|
+
@just_unblanked = false
|
|
154
|
+
p 'ignoring timestamp update ' + to_this_exact_string_might_be_nil if $VERBOSE
|
|
155
|
+
else
|
|
156
|
+
set_seconds OverLayer.translate_string_to_seconds(to_this_exact_string_might_be_nil) + delta if to_this_exact_string_might_be_nil
|
|
157
|
+
end
|
|
149
158
|
end
|
|
150
159
|
|
|
151
160
|
def self.translate_string_to_seconds s
|
|
@@ -176,20 +185,20 @@ class OverLayer
|
|
|
176
185
|
end
|
|
177
186
|
|
|
178
187
|
def status
|
|
179
|
-
time =
|
|
188
|
+
time = cur_english_time
|
|
180
189
|
begin
|
|
181
190
|
mute, blank, next_sig = get_current_state
|
|
182
191
|
if next_sig == :done
|
|
183
|
-
state = " no more
|
|
192
|
+
state = " no more after this point..."
|
|
184
193
|
else
|
|
185
|
-
state = " next
|
|
194
|
+
state = " next will be at #{translate_time_to_human_readable next_sig}s "
|
|
186
195
|
end
|
|
187
196
|
if blank? or muted?
|
|
188
197
|
state += "(" + [muted? ? "muted" : nil, blank? ? "blanked" : nil ].compact.join(' ') + ") "
|
|
189
198
|
end
|
|
190
199
|
end
|
|
191
200
|
check_reload_yaml
|
|
192
|
-
time + state + "(r
|
|
201
|
+
time + state + "(r [or q to quit]): "
|
|
193
202
|
end
|
|
194
203
|
|
|
195
204
|
def keyboard_input char
|
|
@@ -201,6 +210,9 @@ class OverLayer
|
|
|
201
210
|
when 's' then 1
|
|
202
211
|
when 'S' then -1
|
|
203
212
|
when 't' then 0.1
|
|
213
|
+
when 'q' then
|
|
214
|
+
puts '','quitting'
|
|
215
|
+
exit(1)
|
|
204
216
|
when 'T' then -0.1
|
|
205
217
|
when 'v' then
|
|
206
218
|
$VERBOSE = !$VERBOSE
|
data/lib/screen_tracker.rb
CHANGED
|
@@ -7,19 +7,18 @@ class ScreenTracker
|
|
|
7
7
|
|
|
8
8
|
def self.new_from_yaml yaml, callback
|
|
9
9
|
settings = YAML.load yaml
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
digits = settings["digits"]
|
|
13
|
-
return new(settings["name"], settings["x"], settings["y"], settings["width"], settings["height"], digits, callback)
|
|
10
|
+
return new(settings["name"], settings["x"], settings["y"], settings["width"],
|
|
11
|
+
settings["height"], settings["use_class_name"], settings["digits"], callback)
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
attr_accessor :hwnd
|
|
17
15
|
|
|
18
16
|
# digits are like {:hours => [100,5], :minute_tens, :minute_ones, :second_tens, :second_ones}
|
|
19
17
|
# digits share the height start point, have their own x and width...
|
|
20
|
-
def initialize name_or_regex,x,y,width,height,digits=nil,callback=nil
|
|
18
|
+
def initialize name_or_regex,x,y,width,height,use_class_name=nil,digits=nil,callback=nil
|
|
21
19
|
# cache to save us 0.00445136 per time LOL
|
|
22
20
|
@name_or_regex = name_or_regex
|
|
21
|
+
@use_class_name = use_class_name
|
|
23
22
|
get_hwnd
|
|
24
23
|
pps 'height', height, 'width', width if $VERBOSE
|
|
25
24
|
raise 'poor dimentia' if width <= 0 || height <= 0
|
|
@@ -36,7 +35,9 @@ class ScreenTracker
|
|
|
36
35
|
@x = x; @y = y; @x2 = x+width; @y2 = y+height; @callback = callback
|
|
37
36
|
@max_x = max_x
|
|
38
37
|
raise 'poor width or wrong window' if @x2 > max_x || @x2 == x
|
|
39
|
-
|
|
38
|
+
if @y2 > max_y || @y2 == y
|
|
39
|
+
raise 'poor height or wrong window'
|
|
40
|
+
end
|
|
40
41
|
@digits = digits
|
|
41
42
|
@displayed_warning = false
|
|
42
43
|
pps 'using x',@x, 'from x', x, 'y', @y, 'from y', y,'x2',@x2,'y2',@y2,'digits', @digits if $VERBOSE
|
|
@@ -45,19 +46,22 @@ class ScreenTracker
|
|
|
45
46
|
def get_hwnd
|
|
46
47
|
if @name_or_regex.to_s.downcase == 'desktop'
|
|
47
48
|
# full screen option
|
|
49
|
+
assert !@use_class_name # not an option
|
|
48
50
|
@hwnd = hwnd = Win32::Screenshot::BitmapMaker.desktop_window
|
|
51
|
+
return
|
|
49
52
|
else
|
|
50
|
-
@hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex)
|
|
53
|
+
@hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex, @use_class_name)
|
|
51
54
|
end
|
|
52
55
|
|
|
56
|
+
# allow ourselves the 'found it message' selectively
|
|
53
57
|
unless @hwnd
|
|
54
58
|
until @hwnd
|
|
55
|
-
print 'perhaps not running yet? [%s]' % @name_or_regex
|
|
59
|
+
print 'perhaps not running yet? [%s]' % @name_or_regex.inspect
|
|
56
60
|
sleep 1
|
|
57
61
|
STDOUT.flush
|
|
58
|
-
@hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex)
|
|
62
|
+
@hwnd = Win32::Screenshot::BitmapMaker.hwnd(@name_or_regex, @use_class_name)
|
|
59
63
|
end
|
|
60
|
-
puts 'found window'
|
|
64
|
+
puts 're-found window'
|
|
61
65
|
end
|
|
62
66
|
|
|
63
67
|
end
|
|
@@ -77,18 +81,16 @@ class ScreenTracker
|
|
|
77
81
|
def dump_bmp filename = 'dump.bmp'
|
|
78
82
|
File.binwrite filename, get_bmp
|
|
79
83
|
File.binwrite 'all.' + filename, get_full_bmp
|
|
80
|
-
dump_digits
|
|
84
|
+
dump_digits get_digits_as_bitmaps if @digits
|
|
81
85
|
end
|
|
82
86
|
|
|
83
|
-
def dump_digits
|
|
84
|
-
if @digits
|
|
87
|
+
def dump_digits digits
|
|
85
88
|
@digit_count ||= 1
|
|
86
|
-
@digit_count += 1
|
|
87
89
|
for type, bitmap in get_digits_as_bitmaps
|
|
88
90
|
File.binwrite type.to_s + '.' + @digit_count.to_s + '.bmp', bitmap
|
|
89
91
|
end
|
|
90
|
-
print '
|
|
91
|
-
|
|
92
|
+
print 'debug dumped digits that Im about to parse:', @digit_count, "\n"
|
|
93
|
+
@digit_count += 1
|
|
92
94
|
end
|
|
93
95
|
|
|
94
96
|
DIGIT_TYPES = [:hours, :minute_tens, :minute_ones, :second_tens, :second_ones]
|
|
@@ -150,9 +152,17 @@ class ScreenTracker
|
|
|
150
152
|
|
|
151
153
|
def attempt_to_get_time_from_screen
|
|
152
154
|
out = {}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
# force it to have two matching in a row, to avoid race conditions grabbing the digits...
|
|
156
|
+
previous = nil # 0.08s [!] not too accurate...ltodo
|
|
155
157
|
start = Time.now
|
|
158
|
+
until previous == (temp = get_digits_as_bitmaps)
|
|
159
|
+
previous = temp
|
|
160
|
+
sleep 0.05 # allow youtube to update (sigh)
|
|
161
|
+
# lodo it should probably poll *before* this, not here...maybe?
|
|
162
|
+
end
|
|
163
|
+
digits = previous
|
|
164
|
+
|
|
165
|
+
dump_digits(digits) if $DEBUG
|
|
156
166
|
DIGIT_TYPES.each{|type|
|
|
157
167
|
if digits[type]
|
|
158
168
|
digit = identify_digit(digits[type])
|
|
@@ -162,18 +172,19 @@ class ScreenTracker
|
|
|
162
172
|
@a += 1
|
|
163
173
|
@already_wrote ||= {}
|
|
164
174
|
unless @already_wrote[digits[type]]
|
|
165
|
-
p 'unable to identify capture!' + type.to_s + @a.to_s
|
|
175
|
+
p 'unable to identify capture!' + type.to_s + @a.to_s + ' capture no:' + @digit_count.to_s
|
|
166
176
|
File.binwrite("bad_digit#{@a}#{type}.bmp", digits[type]) unless type == :hours
|
|
167
177
|
@already_wrote[digits[type]] = true
|
|
168
178
|
end
|
|
169
179
|
end
|
|
170
180
|
if type == :hours
|
|
171
|
-
digit = 0 # this one can fail in VLC
|
|
181
|
+
digit = 0 # this one can fail and that's ok in VLC bottom right
|
|
172
182
|
else
|
|
173
|
-
# early return
|
|
174
|
-
p 'identity failure ' + type.to_s if $VERBOSE
|
|
183
|
+
# early failure return
|
|
175
184
|
return
|
|
176
185
|
end
|
|
186
|
+
else
|
|
187
|
+
p " got digit #{type} as #{digit} which was captured as #{@digit_count} " if $DEBUG
|
|
177
188
|
end
|
|
178
189
|
out[type] = digit
|
|
179
190
|
else
|
data/never_do
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
== well, probably never :P ==
|
|
2
|
+
|
|
3
|
+
allow x2,y2 for player descriptions...
|
|
4
|
+
|
|
5
|
+
user-assignable "confidence" (how much time to 'wrap' surround the mutes, etc. to accomodate for slow computers/laggy internet/different players/poor input)
|
|
6
|
+
|
|
7
|
+
able to make it "quieter" at certain parts, arbitrarily...
|
|
8
|
+
|
|
9
|
+
OCR the captioning as an auto profanity filter?
|
|
10
|
+
|
|
11
|
+
can overlay with a "fuzzer-outer" for specific coordinates somehow or other...
|
|
12
|
+
|
|
13
|
+
super easy streamer windows -> {XBOX360, wii, etc..} basically playon.tv competitor, which appears to have no free equivalent, I guess, though you can
|
|
14
|
+
Currently it's either a cable, a computer (with its cable), or "ask me for this it might already work"
|
|
15
|
+
todo: refit a VLC version that works *if your soundcard supports it*
|
|
16
|
+
test it on the home PC--does it already work? (i.e. can work OOTB with right card)...
|
|
17
|
+
after: make the same work awesome on doze 7 without quality soundcard :)
|
|
18
|
+
make it work with ps3ms?
|
|
19
|
+
make it work from mac...
|
|
20
|
+
make it work seamlessly with all (XBOX360, wii x2, PS3, bravia)
|
|
21
|
+
also make it into a low quality "skype recorder"
|
|
22
|
+
also can I use a "lesser, faster encoder" to get higher resolution?
|
|
23
|
+
is it faster with ffdshow? mencoder?
|
|
24
|
+
blu-ray
|
|
25
|
+
over wired (?)
|
|
26
|
+
LAN?
|
|
27
|
+
does blu-ray work with HDMI well?
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/spec/ocr.spec.rb
CHANGED
|
@@ -10,38 +10,51 @@ describe OCR do
|
|
|
10
10
|
OCR.version.should_not be_blank
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
Dir['images/*[0-9].bmp'].each{ |file|
|
|
13
|
+
Dir['images/*[0-9].bmp'].sort_by{|f| File.stat(f).mtime}.reverse.each{ |file|
|
|
14
14
|
it "should be able to OCR #{file}" do
|
|
15
|
+
p file if $DEBUG
|
|
15
16
|
options = {}
|
|
16
17
|
options[:should_invert] = true if file =~ /hulu/
|
|
18
|
+
options[:sharpen] = true if file =~ /youtube/
|
|
19
|
+
|
|
20
|
+
# 130 for vlc, 100 for hulu, 0 for some youtube full screen
|
|
21
|
+
# 200, 250 for youtube "light"
|
|
22
|
+
degrees = {'vlc' => [130], 'hulu' => [100], 'youtube' => [0], 'youtube_light' => [200, 250]}
|
|
23
|
+
file =~ /(vlc|hulu|youtube_light|youtube)/
|
|
24
|
+
options[:levels] = degrees[$1]
|
|
25
|
+
assert options[:levels]
|
|
17
26
|
file =~ /(.)\.bmp/
|
|
18
27
|
expected_digit = $1.to_i
|
|
19
|
-
|
|
28
|
+
got_digit = OCR.identify_digit(File.binread(file), options)
|
|
29
|
+
if got_digit != expected_digit
|
|
20
30
|
p "fail:" + file
|
|
21
31
|
begin
|
|
22
|
-
require 'ruby-debug'
|
|
23
|
-
debugger
|
|
32
|
+
#require 'ruby-debug'
|
|
33
|
+
#debugger
|
|
24
34
|
OCR.identify_digit(File.binread(file), options)
|
|
25
35
|
rescue LoadError
|
|
26
36
|
puts 'unable to load ruby-debug'
|
|
27
37
|
end
|
|
28
|
-
|
|
38
|
+
got_digit.should == expected_digit
|
|
29
39
|
end
|
|
30
40
|
end
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
it "should be able to grab a colon" do
|
|
34
|
-
pending "caring about colons"
|
|
35
|
-
|
|
36
|
-
end
|
|
44
|
+
pending "caring about colons"
|
|
45
|
+
OCR.identify_digit(File.binread("images/colon.bmp"), :might_be_colon => true, :levels => [130]).should == ":"
|
|
37
46
|
end
|
|
38
47
|
|
|
39
48
|
def read_digit
|
|
40
|
-
|
|
49
|
+
OCR.identify_digit(File.binread("images/youtube_3_0.bmp"), :sharpen => true, :levels => [130])
|
|
41
50
|
end
|
|
42
51
|
|
|
43
52
|
it "should return nil if it can't identify a digit" do
|
|
44
|
-
|
|
53
|
+
read_all_black.should be_nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def read_all_black
|
|
57
|
+
OCR.identify_digit(File.binread("images/black.bmp"),:levels => [130])
|
|
45
58
|
end
|
|
46
59
|
|
|
47
60
|
context "cache" do
|
|
@@ -62,8 +75,8 @@ describe OCR do
|
|
|
62
75
|
end
|
|
63
76
|
|
|
64
77
|
it "should not cache results for failed reads" do
|
|
65
|
-
original_time = Benchmark.realtime {
|
|
66
|
-
new_time = Benchmark.realtime { 3.times {
|
|
78
|
+
original_time = Benchmark.realtime { read_all_black }
|
|
79
|
+
new_time = Benchmark.realtime { 3.times { read_all_black} }
|
|
67
80
|
new_time.should be > original_time
|
|
68
81
|
end
|
|
69
82
|
|
data/spec/screen_tracker.spec.rb
CHANGED
|
@@ -8,18 +8,19 @@ describe ScreenTracker do
|
|
|
8
8
|
SILENCE = /silence.*VLC/
|
|
9
9
|
|
|
10
10
|
def start_vlc
|
|
11
|
-
# unfortunately this is run before every context with rspec 1.3...
|
|
11
|
+
# unfortunately this is run before every context [bug] with rspec 1.3...
|
|
12
12
|
unless $pid1
|
|
13
13
|
assert !$pid1
|
|
14
|
-
# enforce we only have at most one running
|
|
14
|
+
# enforce we only have at most one running...
|
|
15
15
|
begin
|
|
16
16
|
Win32::Screenshot.window(SILENCE, 0) {}
|
|
17
|
-
raise Exception.new('must
|
|
17
|
+
raise Exception.new('must close existing vlcs first')
|
|
18
18
|
rescue
|
|
19
19
|
silence = File.expand_path("./silence.wav").gsub("/", "\\")
|
|
20
|
-
Dir.chdir("/program files/VideoLan/VLC") do; IO.popen("vlc.exe #{silence}").pid; end # work around for jruby...
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
Dir.chdir("/program files/VideoLan/VLC") do; IO.popen("vlc.exe #{silence}").pid; end # includes a work around for jruby...
|
|
21
|
+
until $pid1
|
|
22
|
+
$pid1 = GetPid.get_process_id_from_window(Win32::Screenshot::Util.window_hwnd(SILENCE)) rescue nil
|
|
23
|
+
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
end
|
|
@@ -169,9 +170,10 @@ describe ScreenTracker do
|
|
|
169
170
|
|
|
170
171
|
it "should be able to disk dump snapshotted digits" do
|
|
171
172
|
@a.dump_bmp
|
|
172
|
-
|
|
173
|
-
Pathname.new('minute_tens.bmp').
|
|
174
|
-
Pathname.new('
|
|
173
|
+
# what is the right number here?
|
|
174
|
+
Pathname.new('minute_tens.1.bmp').should exist
|
|
175
|
+
Pathname.new('minute_tens.1.bmp').size.should be > 0
|
|
176
|
+
Pathname.new('hours.1.bmp').should_not exist
|
|
175
177
|
end
|
|
176
178
|
|
|
177
179
|
it "should use OCR against the changes appropriately" do
|
|
@@ -182,22 +184,46 @@ describe ScreenTracker do
|
|
|
182
184
|
output[1].should be_a Float
|
|
183
185
|
end
|
|
184
186
|
|
|
185
|
-
it "should be ok with a
|
|
187
|
+
it "should be ok with a non-existent hours image" do
|
|
186
188
|
@a.stub!(:get_digits_as_bitmaps) do
|
|
187
|
-
four = File.binread('images/
|
|
189
|
+
four = File.binread('images/vlc_4.bmp')
|
|
190
|
+
black = File.binread('images/black.bmp')
|
|
188
191
|
{:minute_tens=>four,:second_tens => four, :second_ones => four, :minute_ones => four,
|
|
189
|
-
:hours =>
|
|
192
|
+
:hours => black}
|
|
190
193
|
end
|
|
191
194
|
@a.attempt_to_get_time_from_screen[0].should == "0:44:44"
|
|
192
195
|
end
|
|
193
196
|
|
|
197
|
+
it "should track the screen until it stabilizes" do
|
|
198
|
+
time_through = 0
|
|
199
|
+
four = File.binread('images/vlc_4.bmp')
|
|
200
|
+
black = File.binread('images/black.bmp')
|
|
201
|
+
times_read=0
|
|
202
|
+
@a.stub!(:get_digits_as_bitmaps) do
|
|
203
|
+
time_through += 1
|
|
204
|
+
if time_through == 1
|
|
205
|
+
{:minute_tens=>four}
|
|
206
|
+
elsif time_through == 2
|
|
207
|
+
{:minute_tens=>black}
|
|
208
|
+
else
|
|
209
|
+
times_read += 1
|
|
210
|
+
{:minute_tens=>four,:second_tens => four, :second_ones => four, :minute_ones => four,
|
|
211
|
+
:hours => four}
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
@a.attempt_to_get_time_from_screen[0].should == "4:44:44"
|
|
216
|
+
times_read.should == 2
|
|
217
|
+
|
|
218
|
+
end
|
|
219
|
+
|
|
194
220
|
context "with an OCR that can change from hour to minutes during ads" do
|
|
195
221
|
it "should detect this change"
|
|
196
222
|
end
|
|
197
223
|
|
|
198
|
-
it "should be able to use invert on images" do
|
|
199
|
-
@a = ScreenTracker.new(SILENCE,
|
|
200
|
-
{:should_invert => true, :
|
|
224
|
+
it "should be able to use invert on captured images" do
|
|
225
|
+
@a = ScreenTracker.new(SILENCE, 100, 100, 10, 10, false,
|
|
226
|
+
{:should_invert => true, :second_ones => [-66, 7]} )
|
|
201
227
|
got_it = nil
|
|
202
228
|
OCR.stub!(:identify_digit) {|*args|
|
|
203
229
|
got_it = args
|
|
@@ -217,6 +243,12 @@ describe ScreenTracker do
|
|
|
217
243
|
old_handle.should_not == @a.hwnd
|
|
218
244
|
end
|
|
219
245
|
|
|
246
|
+
it "should be able to track via class_name" do
|
|
247
|
+
a = ScreenTracker.new(SILENCE,10,10,20,20)
|
|
248
|
+
b = ScreenTracker.new(/qwidget/i,10,10,20,20, true, {:second_ones => [-66, 7]})
|
|
249
|
+
a.hwnd.should == b.hwnd
|
|
250
|
+
end
|
|
251
|
+
|
|
220
252
|
end
|
|
221
253
|
|
|
222
254
|
def kill_vlc
|
|
@@ -14,4 +14,11 @@ NB that the clock coords can have negative start offsets, which mean "distance f
|
|
|
14
14
|
NB that you can specify "desktop" for the window name, meaning full screen. This is easier, though not necessarily better,
|
|
15
15
|
than finding out the real way.
|
|
16
16
|
|
|
17
|
+
Here is how to specify a regex anywhere:
|
|
18
|
+
|
|
19
|
+
!ruby/regexp /abc/
|
|
20
|
+
|
|
21
|
+
like
|
|
22
|
+
key_name: !ruby/regexp /abc/
|
|
23
|
+
|
|
17
24
|
Post back with difficulties and/or questions.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: !ruby/regexp /nativewindowclass/i
|
|
2
|
+
use_class_name: true
|
|
3
|
+
x: 71
|
|
4
|
+
y : -18
|
|
5
|
+
width: 23
|
|
6
|
+
height: 11
|
|
7
|
+
digits:
|
|
8
|
+
:hours:
|
|
9
|
+
:minute_tens:
|
|
10
|
+
:minute_ones:
|
|
11
|
+
- 72
|
|
12
|
+
- 8
|
|
13
|
+
:second_tens:
|
|
14
|
+
- 82
|
|
15
|
+
- 6
|
|
16
|
+
:second_ones:
|
|
17
|
+
- 88
|
|
18
|
+
- 6
|
|
19
|
+
:levels:
|
|
20
|
+
- 200
|
|
21
|
+
- 250
|
|
22
|
+
:sharpen: true
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# comments can go after the # on each line
|
|
2
|
+
mutes:
|
|
3
|
+
23:03 : 23:05 # all "religious references"
|
|
4
|
+
23:12 : 23:14
|
|
5
|
+
37:02 : 37:03
|
|
6
|
+
37:10 : 37:12
|
|
7
|
+
51:20 : 51:21
|
|
8
|
+
51:27 : 51:28
|
|
9
|
+
|
|
10
|
+
blank_outs:
|
|
11
|
+
58:09 : 1:04:03 # skimpy dancing/costumes in the background
|
|
12
|
+
|
|
13
|
+
title: White Christmas
|
|
14
|
+
source: VLC
|
|
15
|
+
non_got_yet: some of the same material in the previews (it's still there), a few scenes with skimpier clothing
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"profanity categories, so you don't have to write them":
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
euphemized:
|
|
4
|
+
oh my gosh, dang, etc. (these prolly aren't as important to note)
|
|
5
|
+
|
|
6
|
+
religious reference:
|
|
7
|
+
"lord have mercy"
|
|
5
8
|
|
|
6
9
|
religious exclamation:
|
|
7
10
|
da**...
|
|
8
11
|
he**
|
|
12
|
+
|
|
9
13
|
religious exclamation deity:
|
|
10
14
|
oh my ****
|
|
11
15
|
g** d*** ***
|
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
# comments can go after the # on each line
|
|
2
|
-
mutes:
|
|
3
|
-
2.0 : 3.0
|
|
4
|
-
4.0 : 5.0 # mute from second 4 to second 5
|
|
5
|
-
9.0 : 13.0 # mute from second 9 to second 13
|
|
6
|
-
44.0 : 50.0 # mute for 6 seconds starting at second 44
|
|
7
|
-
# This next means mute from one minute to one minute one second
|
|
8
|
-
1:00 : 1:01
|
|
9
|
-
10:01 : 10:02 # mute from ten minutes, one second to ten minutes, 2 seconds
|
|
10
|
-
# if you use decimals, you'll have to put them in quotes
|
|
11
|
-
# 01:01:01.05 (for one hour, one minute, one second and a half) does not work
|
|
12
|
-
# "01:01:01.05" does
|
|
13
|
-
"01:01:00.5" : "01:01:01.5" # mute from one hour one minute and a half second to one hour one minute and 1.5s
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
# comments can go after the # on each line
|
|
2
|
+
mutes:
|
|
3
|
+
2.0 : 3.0
|
|
4
|
+
4.0 : 5.0 # mute from second 4 to second 5
|
|
5
|
+
9.0 : 13.0 # mute from second 9 to second 13
|
|
6
|
+
44.0 : 50.0 # mute for 6 seconds starting at second 44
|
|
7
|
+
# This next means mute from one minute to one minute one second
|
|
8
|
+
1:00 : 1:01
|
|
9
|
+
10:01 : 10:02 # mute from ten minutes, one second to ten minutes, 2 seconds
|
|
10
|
+
# if you use decimals, you'll have to put them in quotes
|
|
11
|
+
# 01:01:01.05 (for one hour, one minute, one second and a half) does not work
|
|
12
|
+
# "01:01:01.05" does
|
|
13
|
+
"01:01:00.5" : "01:01:01.5" # mute from one hour one minute and a half second to one hour one minute and 1.5s
|
|
14
|
+
# items can be out of chronological order
|
|
15
|
+
2.0 : 3.0
|
|
16
|
+
|
|
17
|
+
blank_outs:
|
|
18
|
+
"00:15" : "00:18" # blank from second 15 to 18
|
|
19
|
+
01:01 : "01:02.0" # blank from one minute one second to one minute two seconds, etc.
|
|
20
|
+
1:00:00 : 1:00:30 # note also that if you blank something out it isn't muted unless you *also* add it to the mute list, above. Message me if you want that changed.
|
|
21
|
+
|
|
22
|
+
title: Forever Strong
|
|
23
|
+
source: Hulu # these aren't required fields -- mutes and blank_outs are
|
|
24
|
+
something_else: "for now you can add whatever categories you want, like what_it_would_now_be_rated
|
|
25
|
+
what_aspects_were_not_able_to_be_removed, url, DVD label, etc, though in reality the only required ones are mutes and blank_outs"
|
|
26
|
+
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
mutes:
|
|
2
|
-
# none
|
|
3
|
-
blank_outs:
|
|
4
|
-
"0:01:02" : "0:01:06" # bum waggin'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
mutes:
|
|
2
|
+
# none
|
|
3
|
+
blank_outs:
|
|
4
|
+
"0:01:02" : "0:01:06.5" # bum waggin'
|
|
5
|
+
0:02:17.5 : 0:02:19
|
|
6
|
+
|
|
7
|
+
title: The Gummy Bear Song - Long English Version (probably works with other languages')
|
|
8
|
+
source: youtube
|
|
8
9
|
url: http://www.youtube.com/watch?v=astISOttCQ0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
mutes:
|
|
2
|
-
# none
|
|
3
|
-
blank_outs:
|
|
4
|
-
# bum wigglin'
|
|
5
|
-
"00:46.5" : "00:
|
|
6
|
-
"02:18.5" : "02:20"
|
|
7
|
-
title: Nuki Song
|
|
8
|
-
source: youtube
|
|
9
|
-
url: http://www.youtube.com/watch?v=xd12hR68sWM
|
|
1
|
+
mutes:
|
|
2
|
+
# none
|
|
3
|
+
blank_outs:
|
|
4
|
+
# bum wigglin'
|
|
5
|
+
"00:46.5" : "00:49"
|
|
6
|
+
"02:18.5" : "02:20"
|
|
7
|
+
title: Nuki Song
|
|
8
|
+
source: youtube
|
|
9
|
+
url: http://www.youtube.com/watch?v=xd12hR68sWM
|
metadata
CHANGED
|
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
|
5
5
|
segments:
|
|
6
6
|
- 0
|
|
7
7
|
- 9
|
|
8
|
-
-
|
|
9
|
-
version: 0.9.
|
|
8
|
+
- 4
|
|
9
|
+
version: 0.9.4
|
|
10
10
|
platform: ruby
|
|
11
11
|
authors:
|
|
12
12
|
- Roger Pack
|
|
@@ -14,7 +14,7 @@ autorequire:
|
|
|
14
14
|
bindir: bin
|
|
15
15
|
cert_chain: []
|
|
16
16
|
|
|
17
|
-
date: 2010-
|
|
17
|
+
date: 2010-09-12 00:00:00 -06:00
|
|
18
18
|
default_executable: sensible-cinema
|
|
19
19
|
dependencies:
|
|
20
20
|
- !ruby/object:Gem::Dependency
|
|
@@ -43,9 +43,9 @@ dependencies:
|
|
|
43
43
|
segments:
|
|
44
44
|
- 0
|
|
45
45
|
- 0
|
|
46
|
-
-
|
|
46
|
+
- 7
|
|
47
47
|
- 3
|
|
48
|
-
version: 0.0.
|
|
48
|
+
version: 0.0.7.3
|
|
49
49
|
type: :runtime
|
|
50
50
|
version_requirements: *id002
|
|
51
51
|
- !ruby/object:Gem::Dependency
|
|
@@ -141,10 +141,10 @@ files:
|
|
|
141
141
|
- lib/ocr.rb
|
|
142
142
|
- lib/overlayer.rb
|
|
143
143
|
- lib/screen_tracker.rb
|
|
144
|
+
- never_do
|
|
144
145
|
- spec/blanker.spec.rb
|
|
145
146
|
- spec/common.rb
|
|
146
147
|
- spec/convert_image.rb
|
|
147
|
-
- spec/images/4.bmp
|
|
148
148
|
- spec/images/black.bmp
|
|
149
149
|
- spec/images/colon.bmp
|
|
150
150
|
- spec/images/hulu_0.bmp
|
|
@@ -160,6 +160,7 @@ files:
|
|
|
160
160
|
- spec/images/hulu_8.bmp
|
|
161
161
|
- spec/images/hulu_slash.bmp
|
|
162
162
|
- spec/images/vlc_0.bmp
|
|
163
|
+
- spec/images/vlc_2_4.bmp
|
|
163
164
|
- spec/images/vlc_2_6.bmp
|
|
164
165
|
- spec/images/vlc_4.bmp
|
|
165
166
|
- spec/images/vlc_5.bmp
|
|
@@ -169,6 +170,7 @@ files:
|
|
|
169
170
|
- spec/images/youtube_0.bmp
|
|
170
171
|
- spec/images/youtube_1.bmp
|
|
171
172
|
- spec/images/youtube_2_0.bmp
|
|
173
|
+
- spec/images/youtube_2_3.bmp
|
|
172
174
|
- spec/images/youtube_2_5.bmp
|
|
173
175
|
- spec/images/youtube_2_6.bmp
|
|
174
176
|
- spec/images/youtube_3_0.bmp
|
|
@@ -176,6 +178,15 @@ files:
|
|
|
176
178
|
- spec/images/youtube_4_0.bmp
|
|
177
179
|
- spec/images/youtube_5.bmp
|
|
178
180
|
- spec/images/youtube_6.bmp
|
|
181
|
+
- spec/images/youtube_light_0.bmp
|
|
182
|
+
- spec/images/youtube_light_2_1.bmp
|
|
183
|
+
- spec/images/youtube_light_2_3.bmp
|
|
184
|
+
- spec/images/youtube_light_4.bmp
|
|
185
|
+
- spec/images/youtube_light_4_3.bmp
|
|
186
|
+
- spec/images/youtube_light_5.bmp
|
|
187
|
+
- spec/images/youtube_light_5_0.bmp
|
|
188
|
+
- spec/images/youtube_light_8.bmp
|
|
189
|
+
- spec/images/youtube_light_9.bmp
|
|
179
190
|
- spec/images/youtube_small_0.bmp
|
|
180
191
|
- spec/images/youtube_small_2.bmp
|
|
181
192
|
- spec/images/youtube_small_2_0.bmp
|
|
@@ -212,18 +223,21 @@ files:
|
|
|
212
223
|
- vendor/imagemagick/msvcp90.dll
|
|
213
224
|
- vendor/imagemagick/msvcr90.dll
|
|
214
225
|
- vendor/imagemagick/vcomp90.dll
|
|
215
|
-
- zamples/players/
|
|
226
|
+
- zamples/players/how_to_create_more.txt
|
|
216
227
|
- zamples/players/hulu/total_length_over_an_hour.yml
|
|
217
228
|
- zamples/players/vlc/full_screened_total_length_over_an_hour.yml
|
|
218
|
-
- zamples/players/vlc/
|
|
219
|
-
- zamples/players/vlc/
|
|
229
|
+
- zamples/players/vlc/windowed_total_length_over_an_hour.yml
|
|
230
|
+
- zamples/players/vlc/windowed_total_length_under_an_hour.yml
|
|
220
231
|
- zamples/players/youtube/full_screened_1024x768.yml
|
|
221
232
|
- zamples/players/youtube/full_screened_1152x864.yml
|
|
222
233
|
- zamples/players/youtube/full_screened_1680x1050.yml
|
|
234
|
+
- zamples/players/youtube/normal_in_youtube.com.yml
|
|
223
235
|
- zamples/players/youtube/note_these_assume_less_than_10_minutes_length.txt
|
|
236
|
+
- zamples/scene_lists/White Christmas.yml
|
|
237
|
+
- zamples/scene_lists/all_dogs_go_to_heaven_dvd.yml
|
|
224
238
|
- zamples/scene_lists/category descriptions.yml
|
|
225
239
|
- zamples/scene_lists/disney_cars.yml
|
|
226
|
-
- zamples/scene_lists/
|
|
240
|
+
- zamples/scene_lists/example_scene_descriptions_list.yml
|
|
227
241
|
- zamples/scene_lists/gummy_bear_song_youtube.yml
|
|
228
242
|
- zamples/scene_lists/happy_feet_dvd.yml
|
|
229
243
|
- zamples/scene_lists/labyrinth.yml
|