vodstamp 0.1.0
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/bin/vodstamp +28 -0
- data/lib/vodstamp.rb +207 -0
- metadata +48 -0
data/bin/vodstamp
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
require 'vodstamp'
|
|
5
|
+
|
|
6
|
+
if ARGV.length > 0
|
|
7
|
+
vodstamp = Vodstamp.new;
|
|
8
|
+
actual_command = ARGV.shift
|
|
9
|
+
command = actual_command.gsub ':', '_'
|
|
10
|
+
if vodstamp.respond_to? command
|
|
11
|
+
vodstamp.send command, ARGV
|
|
12
|
+
else # ! vodstamp.respond_to? command
|
|
13
|
+
puts " err: unknown command #{actual_command}"
|
|
14
|
+
end#if
|
|
15
|
+
else # ARGV.length == 0
|
|
16
|
+
|
|
17
|
+
puts
|
|
18
|
+
puts <<eos
|
|
19
|
+
Commands
|
|
20
|
+
------------------------------------------------------------------------------
|
|
21
|
+
vodstamp version - current version
|
|
22
|
+
vodstamp all <input> <output> - filter timestamp messages based only on marker
|
|
23
|
+
vodstamp filter <input> <output> <source> - filter timestamp messages from a chat log
|
|
24
|
+
vodstamp build <input> <output> <splits> <offset> - build timestamps
|
|
25
|
+
|
|
26
|
+
eos
|
|
27
|
+
|
|
28
|
+
end#if
|
data/lib/vodstamp.rb
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
class Vodstamp
|
|
2
|
+
|
|
3
|
+
VERSION = '0.1.0'
|
|
4
|
+
|
|
5
|
+
#### Commands ##################################################################
|
|
6
|
+
|
|
7
|
+
def version(args)
|
|
8
|
+
puts " #{Vodstamp::VERSION}"
|
|
9
|
+
end#def
|
|
10
|
+
|
|
11
|
+
def all(args)
|
|
12
|
+
msg "filtering all from [#{args[0]}] to [#{args[1]}]"
|
|
13
|
+
|
|
14
|
+
inputfile = File.expand_path(args[0]);
|
|
15
|
+
outputfile = File.expand_path(args[1]);
|
|
16
|
+
|
|
17
|
+
if ! File.exist? inputfile
|
|
18
|
+
err "The file [#{inputfile}] does not exist."
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
rawlog = File.read inputfile
|
|
22
|
+
rawlog = rawlog.split "\n"
|
|
23
|
+
|
|
24
|
+
log = filter_chatlog true, rawlog, arg[2]
|
|
25
|
+
|
|
26
|
+
File.write(outputfile, log.join("\n"))
|
|
27
|
+
msg "fin"
|
|
28
|
+
end#def
|
|
29
|
+
|
|
30
|
+
def filter(args)
|
|
31
|
+
msg "filtering [#{args[0]}] to [#{args[1]}] using source [#{args[2]}]"
|
|
32
|
+
|
|
33
|
+
inputfile = File.expand_path(args[0]);
|
|
34
|
+
outputfile = File.expand_path(args[1]);
|
|
35
|
+
|
|
36
|
+
if ! File.exist? inputfile
|
|
37
|
+
err "The file [#{inputfile}] does not exist."
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
rawlog = File.read inputfile
|
|
41
|
+
rawlog = rawlog.split "\n"
|
|
42
|
+
|
|
43
|
+
filter_chatlog false, rawlog, args[2]
|
|
44
|
+
|
|
45
|
+
File.write(outputfile, log.join("\n"))
|
|
46
|
+
msg "fin"
|
|
47
|
+
end#def
|
|
48
|
+
|
|
49
|
+
def build(args)
|
|
50
|
+
msg "building from [#{args[0]}] to [#{args[1]}] with splits [#{args[2]}] and offset of #{args[3]} seconds"
|
|
51
|
+
|
|
52
|
+
inputfile = File.expand_path(args[0]);
|
|
53
|
+
outputfile = File.expand_path(args[1]);
|
|
54
|
+
splitsfile = File.expand_path(args[2]);
|
|
55
|
+
|
|
56
|
+
if ! File.exist? inputfile
|
|
57
|
+
err "The file [#{inputfile}] does not exist."
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if ! File.exist? splitsfile
|
|
61
|
+
err "The file [#{splitsfile}] does not exist."
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
rawlog = File.read inputfile
|
|
65
|
+
rawlog = rawlog.split "\n"
|
|
66
|
+
|
|
67
|
+
rawsplits = File.read splitsfile
|
|
68
|
+
rawsplits = rawsplits.split "\n"
|
|
69
|
+
|
|
70
|
+
timestamps = build_timestamps rawlog, rawsplits, args[3].to_i
|
|
71
|
+
|
|
72
|
+
File.write(outputfile, timestamps.join("\n"))
|
|
73
|
+
msg "fin"
|
|
74
|
+
end#def
|
|
75
|
+
|
|
76
|
+
#### Working Methods ###########################################################
|
|
77
|
+
|
|
78
|
+
def build_timestamps(rawlog, rawsplits, offset)
|
|
79
|
+
# parse timestamps
|
|
80
|
+
logpattern = /[a-zA-Z]+ [0-9]+ ([0-9]{2}):([0-9]{2}):([0-9]{2}) <([a-zA-Z0-9_-]+)> \[timestamp\] (T-([0-9]{2}):([0-9]{2}) (.*)|ignore last|todo|realign)/
|
|
81
|
+
log = [];
|
|
82
|
+
diff = nil
|
|
83
|
+
rawlog.each do |line|
|
|
84
|
+
match = logpattern.match(line)
|
|
85
|
+
next if match[6] == nil
|
|
86
|
+
# get data
|
|
87
|
+
h = match[1].to_i
|
|
88
|
+
m = match[2].to_i
|
|
89
|
+
s = match[3].to_i
|
|
90
|
+
om = match[6].to_i
|
|
91
|
+
os = match[7].to_i
|
|
92
|
+
message = match[8]
|
|
93
|
+
# convert to seconds
|
|
94
|
+
time_s = s + m * 60 + h * 60 * 60
|
|
95
|
+
offset_s = os + om * 60
|
|
96
|
+
|
|
97
|
+
if diff === nil
|
|
98
|
+
diff = time_s - offset_s
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
time_s = time_s - offset_s - diff
|
|
102
|
+
log.push({ time: time_s, msg: message })
|
|
103
|
+
end#each
|
|
104
|
+
|
|
105
|
+
# parse splits
|
|
106
|
+
splitpattern = /([a-zA-Z0-9 ]+)\. ([0-9]{2}):([0-9]{2}):([0-9]{2})/
|
|
107
|
+
splits = []
|
|
108
|
+
rawsplits.each do |line|
|
|
109
|
+
match = splitpattern.match(line)
|
|
110
|
+
h = match[2].to_i
|
|
111
|
+
m = match[3].to_i
|
|
112
|
+
s = match[4].to_i
|
|
113
|
+
# convert to seconds
|
|
114
|
+
time_s = s + m * 60 + h * 60 * 60
|
|
115
|
+
splits.push({ time: time_s, name: match[1] })
|
|
116
|
+
end#each
|
|
117
|
+
|
|
118
|
+
# generate timestamps
|
|
119
|
+
times = []
|
|
120
|
+
splitidx = 0
|
|
121
|
+
this_split = splits[splitidx]
|
|
122
|
+
split_max_time = this_split[:time]
|
|
123
|
+
split_diff = -offset
|
|
124
|
+
times.push([]);
|
|
125
|
+
log.each do |entry|
|
|
126
|
+
if offset + entry[:time] > split_max_time
|
|
127
|
+
split_diff += this_split[:time]
|
|
128
|
+
splitidx += 1
|
|
129
|
+
this_split = splits[splitidx]
|
|
130
|
+
split_max_time += this_split[:time]
|
|
131
|
+
times.push([])
|
|
132
|
+
end
|
|
133
|
+
times[splitidx].push({ time: entry[:time] - split_diff, msg: entry[:msg] })
|
|
134
|
+
end#each
|
|
135
|
+
|
|
136
|
+
timestamps = []
|
|
137
|
+
idx = 0
|
|
138
|
+
|
|
139
|
+
print " " # progress prefix
|
|
140
|
+
times.each do |stamps|
|
|
141
|
+
timestamps.push " -- #{splits[idx][:name]} -- "
|
|
142
|
+
stamps.each do |time|
|
|
143
|
+
minutes = (time[:time] / 60).to_i
|
|
144
|
+
seconds = time[:time] - minutes * 60
|
|
145
|
+
timestamps.push readable_time(time[:time]) + " #{time[:msg]}"
|
|
146
|
+
print '.' # progress indicator
|
|
147
|
+
end#each
|
|
148
|
+
idx += 1
|
|
149
|
+
end#each
|
|
150
|
+
puts
|
|
151
|
+
|
|
152
|
+
return timestamps;
|
|
153
|
+
end#def
|
|
154
|
+
|
|
155
|
+
def filter_chatlog(all_messages, rawlog, source = nil)
|
|
156
|
+
log = []
|
|
157
|
+
|
|
158
|
+
if all_messages
|
|
159
|
+
logpattern = /.* \[timestamp\] .*/
|
|
160
|
+
else # only correct ones
|
|
161
|
+
logpattern = /[a-zA-Z]+ [0-9]+ ([0-9]{2}):([0-9]{2}):([0-9]{2}) <([a-zA-Z0-9_-]+)> \[timestamp\] (T-([0-9]{2}):([0-9]{2}) .*|ignore last|todo|realign)/
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
ignorepattern = /\[timestamp\] ignore last/
|
|
165
|
+
|
|
166
|
+
print " " # progress prefix
|
|
167
|
+
rawlog.each do |line|
|
|
168
|
+
if (match = logpattern.match(line)) != nil
|
|
169
|
+
if all_messages || match[4] == source
|
|
170
|
+
if ! all_messages && ignorepattern.match(line) != nil
|
|
171
|
+
log.pop
|
|
172
|
+
print ',' # indicate backtracking
|
|
173
|
+
else # normal line
|
|
174
|
+
log.push line
|
|
175
|
+
print '.' # indicate progress
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end#each
|
|
180
|
+
puts # new line at end of progress
|
|
181
|
+
|
|
182
|
+
return log
|
|
183
|
+
end#def
|
|
184
|
+
|
|
185
|
+
#### Helpers ###################################################################
|
|
186
|
+
|
|
187
|
+
def readable_time(time)
|
|
188
|
+
hours = (time / 3600).to_i
|
|
189
|
+
minutes = ((time - hours) / 60).to_i
|
|
190
|
+
seconds = time - hours * 3600 - minutes * 60
|
|
191
|
+
if hours != 0
|
|
192
|
+
return ('%02d' % hours) + ':' + ('%02d' % minutes) + ':' + ('%02d' % seconds)
|
|
193
|
+
else
|
|
194
|
+
return ('%02d' % minutes) + ':' + ('%02d' % seconds)
|
|
195
|
+
end
|
|
196
|
+
end#def
|
|
197
|
+
|
|
198
|
+
def err(msg)
|
|
199
|
+
puts " Err: #{msg}"
|
|
200
|
+
exit
|
|
201
|
+
end#def
|
|
202
|
+
|
|
203
|
+
def msg(msg)
|
|
204
|
+
puts " #{msg}"
|
|
205
|
+
end#def
|
|
206
|
+
|
|
207
|
+
end#class
|
metadata
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vodstamp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- srcspider
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: Video timestamping tool
|
|
15
|
+
email: source.spider@gmail.com
|
|
16
|
+
executables:
|
|
17
|
+
- vodstamp
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- lib/vodstamp.rb
|
|
22
|
+
- bin/vodstamp
|
|
23
|
+
homepage: http://rubygems.org/gems/vodstamp
|
|
24
|
+
licenses:
|
|
25
|
+
- MIT
|
|
26
|
+
post_install_message:
|
|
27
|
+
rdoc_options: []
|
|
28
|
+
require_paths:
|
|
29
|
+
- lib
|
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
|
+
none: false
|
|
32
|
+
requirements:
|
|
33
|
+
- - ! '>='
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: '0'
|
|
36
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
37
|
+
none: false
|
|
38
|
+
requirements:
|
|
39
|
+
- - ! '>='
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
requirements: []
|
|
43
|
+
rubyforge_project:
|
|
44
|
+
rubygems_version: 1.8.28
|
|
45
|
+
signing_key:
|
|
46
|
+
specification_version: 3
|
|
47
|
+
summary: video timestamping tool
|
|
48
|
+
test_files: []
|