timestamp_maker 1.0.2

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 01abd157048ff7bdbf8fee5cd139f8e238c48dc82850202aa4f9c7748d7bf8da
4
+ data.tar.gz: 7c94cd8a48aab112d17a48f97112cb5594fd517415518202e0dc6074e1b707a0
5
+ SHA512:
6
+ metadata.gz: 48cf23b7cb6c1526825316f148875a7554371e7e3c2ca5716a3e33b7585277789a7d698d4b0811eb60c59d445af742e16b43a3c454d68365f372f428db245f0a
7
+ data.tar.gz: 9b1d3b546e5a0ac019efb0f46fa2763b40614e0efb406b38e5430d96fbb8540d99b92d7f34fcafe86f19e34fd91b70319ea7240ad9b1c9ee88d1f55c1c021c8b
data/bin/timestamp ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'timestamp_maker'
5
+ require 'optparse'
6
+
7
+ option_parser = OptionParser.new do |opts|
8
+ opts.banner = "Usage: #{__FILE__} INPUT_FILE_PATH OUTPUT_FILE_PATH"
9
+ end
10
+ option_parser.parse!
11
+
12
+ if ARGV.length != 2
13
+ puts option_parser
14
+ exit 1
15
+ end
16
+
17
+ input = ARGV.shift
18
+ output = ARGV.shift
19
+
20
+ TimestampMaker.add_timestamp(input, output)
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'marcel'
4
+ require 'pathname'
5
+ require 'timestamp_maker/video_timestamper'
6
+ require 'timestamp_maker/mime_recognizer'
7
+ require 'timestamp_maker/image_timestamper'
8
+
9
+ module TimestampMaker
10
+ @mime_recognizer = MimeRecognizer
11
+ @image_timestamper = ImageTimestamper
12
+ @video_timestamper = VideoTimestamper
13
+
14
+ class << self
15
+ attr_reader :mime_recognizer, :image_timestamper, :video_timestamper
16
+
17
+ def add_timestamp(input_path, output_path)
18
+ mime_type = mime_recognizer.recognize(input_path)
19
+ processor =
20
+ case mime_type.split('/').first
21
+ when 'image' then image_timestamper
22
+ when 'video' then video_timestamper
23
+ else raise "Unsupported MIME type: ##{mime_type}"
24
+ end
25
+ processor.add_timestamp(input_path, output_path)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'time'
5
+
6
+ module TimestampMaker
7
+ module ImageTimestamper
8
+ def self.add_timestamp(input_path, output_path)
9
+ time_string = creation_time(input_path).iso8601
10
+ command = %W[
11
+ magick convert #{input_path}
12
+ (
13
+ -background rgba(0,0,0,0.7)
14
+ -fill white
15
+ -font Roboto
16
+ -pointsize 32
17
+ -gravity NorthWest
18
+ -splice 1x1
19
+ -gravity SouthEast
20
+ -splice 1x1
21
+ label:#{time_string}
22
+ )
23
+ -gravity NorthWest -geometry +32+32 -composite #{output_path}
24
+ ]
25
+ system(*command, exception: true)
26
+ end
27
+
28
+ def self.creation_time(input_path)
29
+ command = %W[
30
+ magick identify -format %[exif:DateTime*]%[exif:OffsetTime*] #{input_path}
31
+ ]
32
+
33
+ stdout_string, status = Open3.capture2(*command)
34
+ raise unless status.success?
35
+
36
+ parsed = Hash[stdout_string.split("\n").map!{ _1[5..].split('=') }]
37
+
38
+ time_string = parsed['DateTimeOriginal'] || parsed['DateTimeDigitized'] || parsed['DateTime']
39
+ raise 'Cannot find creation time' if time_string.nil?
40
+
41
+ time_offset_string = parsed['OffsetTimeOriginal'] || parsed['OffsetTimeDigitized'] || parsed['OffsetTime'] || 'Z'
42
+
43
+ Time.strptime("#{time_string} #{time_offset_string}", '%Y:%m:%d %H:%M:%S %Z')
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimestampMaker
4
+ module MimeRecognizer
5
+ def self.recognize(path)
6
+ Marcel::MimeType.for(Pathname.new(path))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'time'
5
+ require 'open3'
6
+ require 'shellwords'
7
+
8
+ module TimestampMaker
9
+ module VideoTimestamper
10
+ def self.add_timestamp(input_path, output_path)
11
+ creation_timestamp = creation_time(input_path).to_i
12
+ drawtext = %W[
13
+ x=32
14
+ y=32
15
+ font=Roboto
16
+ fontsize=32
17
+ fontcolor=white
18
+ box=1
19
+ boxcolor=black@0.7
20
+ boxborderw=8
21
+ text=%{pts\\\\:localtime\\\\:#{creation_timestamp}}
22
+ ].join(':')
23
+
24
+ command = %W[
25
+ ffmpeg -y -v warning -i #{input_path} -map_metadata 0
26
+ -vf drawtext=#{drawtext}
27
+ #{output_path}
28
+ ]
29
+
30
+ system(*command, exception: true)
31
+ end
32
+
33
+ def self.creation_time(input_path)
34
+ command = %W[
35
+ ffprobe -v warning -print_format json -show_entries format_tags=creation_time #{Shellwords.escape(input_path)}
36
+ ]
37
+ stdout_string, status = Open3.capture2(*command)
38
+ raise unless status.success?
39
+
40
+ parsed = JSON.parse(stdout_string)
41
+ iso8601_string = parsed['format']['tags']['creation_time']
42
+ raise 'Cannot find creation time' if iso8601_string.nil?
43
+
44
+ Time.iso8601(iso8601_string)
45
+ end
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timestamp_maker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Weihang Jian
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-07-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: marcel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ description: timestamp_maker is a command-line tool that adds timestamp to images
56
+ and videos.
57
+ email: tonytonyjan@gmail.com
58
+ executables:
59
+ - timestamp
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - bin/timestamp
64
+ - lib/timestamp_maker.rb
65
+ - lib/timestamp_maker/image_timestamper.rb
66
+ - lib/timestamp_maker/mime_recognizer.rb
67
+ - lib/timestamp_maker/video_timestamper.rb
68
+ homepage: https://github.com/tonytonyjan/timestamp_maker
69
+ licenses:
70
+ - MIT
71
+ metadata:
72
+ source_code_uri: https://github.com/tonytonyjan/timestamp_maker
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.2.22
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: timestamp_maker is a command-line tool that adds timestamp to images and
92
+ videos.
93
+ test_files: []