screengif 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ .bundle/
2
+ vendor/
3
+ Gemfile.lock
4
+
5
+ output
6
+ build
7
+ *.gem
8
+
9
+ *.swp
10
+ *.swo
@@ -0,0 +1,54 @@
1
+ screengif dev notes
2
+ ===================
3
+
4
+ ## Building the gem
5
+
6
+ See [vagrant-vbox-manage/DEVNOTES.md](https://github.com/dergachev/vagrant-vbox-snapshot/blob/master/DEVNOTES.md)
7
+
8
+ ```
9
+ gem build screengif.gemspec
10
+ gem install screengif-0.0.1.gem
11
+ screengif -i=demo.mov -o demo5.gif
12
+ ```
13
+
14
+ ### Related solutions
15
+
16
+ * http://freezeframe.chrisantonellis.com/ (js library to freeze/play gifs)
17
+ * http://askubuntu.com/questions/107726/how-to-create-animated-gif-images-of-a-screencast
18
+
19
+ ### RMagick
20
+
21
+ * http://railscasts.com/episodes/374-image-manipulation?view=asciicast
22
+ * http://ruby.bastardsbook.com/chapters/image-manipulation/
23
+ * https://github.com/markandrus/imgswiss/blob/master/pipeline.rb (ffmpeg -> imagemagick via rmagick -> gif)
24
+
25
+ * http://www.imagemagick.org/RMagick/doc/info.html#format
26
+ * http://www.imagemagick.org/RMagick/doc/draw.html#rectangle
27
+ * http://www.imagemagick.org/RMagick/doc/constants.html#GravityType
28
+ * http://www.simplesystems.org/RMagick/doc/optequiv.html
29
+ * http://www.imagemagick.org/RMagick/doc/ilist.html
30
+ * http://www.imagemagick.org/RMagick/doc/clip_path.rb.html (define_clip_path example)
31
+
32
+ ### Imagemagick
33
+
34
+ * http://www.imagemagick.org/Usage/draw/
35
+ * http://www.imagemagick.org/Usage/anim_opt/
36
+ * http://www.imagemagick.org/Usage/transform/#fx
37
+ * http://www.imagemagick.org/Usage/layers/
38
+ * http://www.imagemagick.org/script/command-line-options.php#delete
39
+ * http://www.imagemagick.org/script/fx.php
40
+ * http://www.imagemagick.org/script/escape.php
41
+ * http://www.imagemagick.org/Usage/annotating/#watermarking
42
+ * http://www.imagemagick.org/Usage/anim_mods/#frame_mod
43
+ * http://www.ioncannon.net/linux/81/5-imagemagick-command-line-examples-part-1/
44
+
45
+ ## Bash guides
46
+
47
+ * http://andreinc.net/2011/09/04/bash-scripting-best-practice/
48
+ * http://stackoverflow.com/questions/242538/unix-shell-script-find-out-which-directory-the-script-file-resides
49
+
50
+ ## Ruby guides
51
+
52
+ * TODO: implement tests; see https://github.com/pgericson/progress_bar/blob/master/test/arguments_test.rb
53
+ * TODO: look at mixlib-{shellout,cli,logger}; https://github.com/opscode/mixlib-shellout
54
+ * TODO: look at https://github.com/bitboxer/simple_progressbar/blob/master/lib/simple_progressbar.rb
@@ -0,0 +1,28 @@
1
+ FROM ubuntu:14.04
2
+
3
+ # If host is running squid-deb-proxy on port 8000, populate /etc/apt/apt.conf.d/30proxy
4
+ # By default, squid-deb-proxy 403s unknown sources, so apt shouldn't proxy ppa.launchpad.net
5
+ RUN route -n | awk '/^0.0.0.0/ {print $2}' > /tmp/host_ip.txt
6
+ RUN echo "HEAD /" | nc `cat /tmp/host_ip.txt` 8000 | grep squid-deb-proxy \
7
+ && (echo "Acquire::http::Proxy \"http://$(cat /tmp/host_ip.txt):8000\";" > /etc/apt/apt.conf.d/30proxy) \
8
+ && (echo "Acquire::http::Proxy::ppa.launchpad.net DIRECT;" >> /etc/apt/apt.conf.d/30proxy) \
9
+ || echo "No squid-deb-proxy detected on docker host"
10
+
11
+ RUN apt-get update
12
+
13
+ RUN apt-get install -y imagemagick
14
+ RUN apt-get install -y libmagickwand-dev
15
+ RUN apt-get install -y gifsicle
16
+ RUN apt-get -y install ruby1.9.1 ruby1.9.1-dev
17
+ RUN apt-get install -y build-essential curl git vim
18
+
19
+ RUN apt-get install -y python-software-properties software-properties-common
20
+ RUN add-apt-repository ppa:mc3man/trusty-media
21
+ RUN apt-get update
22
+ RUN apt-get -y install ffmpeg
23
+
24
+ RUN gem install bundler --no-rdoc --no-ri
25
+ ADD Gemfile /tmp/Gemfile
26
+ RUN cd /tmp; bundle install
27
+
28
+ WORKDIR /srv/screengif
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rmagick'
@@ -0,0 +1,20 @@
1
+ build:
2
+ docker build -t dergachev/screengif .
3
+
4
+ cmd=/bin/bash
5
+ docker-run:
6
+ docker run -t -i \
7
+ -v `pwd`:/srv/screengif \
8
+ dergachev/screengif \
9
+ /bin/bash -c "umask 002; $(cmd) $(args)"
10
+
11
+ docker-bash:
12
+ $(MAKE) docker-run cmd="/bin/bash"
13
+
14
+ docker-convert:
15
+ $(MAKE) docker-run cmd="bin/screengif" args="$(args)"
16
+
17
+ docker-shell:
18
+ $(MAKE) docker-run cmd="/bin/bash"
19
+
20
+ .PHONY: build docker-run docker-convert docker-shell
@@ -0,0 +1,111 @@
1
+ # Screengif
2
+
3
+ A commandline tool to convert SCREENCAST.mov into ANIMATED.gif
4
+
5
+ Here's what happens when you apply it to [demo.mov](https://raw.github.com/dergachev/screengif/master/demo.mov)
6
+
7
+ <img src="https://raw.github.com/dergachev/screengif/master/demo.gif" width="400" />
8
+
9
+ ## Usage
10
+
11
+ ```
12
+ screengif.rb - Convert your screencast into a gif.
13
+ Usage:
14
+ screengif.rb [options] [--input FILENAME.mov] [--output OUTPUTFILE.gif]
15
+ Examples:
16
+ ./screengif.rb --input demo.mov --output out.gif
17
+ cat somefile.gif | ./screengif.rb --progressbar --framerate 10 --delay 50 --delay-last 5 > out.gif
18
+
19
+ Specific options:
20
+ -i, --input FILENAME.mov Use ffmpeg to convert FILENAME.mov into PPM image stream and process results.
21
+ If missing, will process PPM or GIF image stream from STDIN.
22
+ -o, --output FILENAME.gif Output resulting GIF data to FILENAME.gif. (defaults to STDOUT).
23
+ -p, --progressbar Overlay progress bar on the animation.
24
+ -d, --delay MS Animation frame delay, in tens of ms. (default: 10)
25
+ --delay-last MS Animation frame delay of last frame, in tens of ms. (default: 50)
26
+ -r, --framerate FPS Specify amount of frames per second to keep. (default: 5)
27
+ -w, --max-width PIXELS Output image max width, in pixels.
28
+ --max-height PIXELS Output image max height, in pixels.
29
+ --no-contrast Skip increasing contrast using imagemagick.
30
+ -f, --fuzz PERCENT Imagemagick fuzz factor for color reduction. (default: 5%)
31
+ --no-coalesce Skip Magick::ImageList#coalesce() if input doesn't need it.
32
+ --no-gifsicle Prevent filter the output through gifsicle. Greatly increases output file size.
33
+ -h, --help Show this message
34
+ -v, --verbose Verbose output
35
+ --version Show version
36
+ ```
37
+
38
+ ## Installation
39
+
40
+ ### Under Docker
41
+
42
+ If you have docker running, this is the quickest way to get
43
+ started with screengif:
44
+
45
+ ```
46
+ git clone git@github.com:dergachev/screengif.git
47
+ cd screengif
48
+
49
+ make build # or alternatively, 'docker pull dergachev/screengif'
50
+
51
+ make docker-convert args="-i demo.mov -o demo-docker.gif"
52
+
53
+ # input files must be relative to cloned screengif repo
54
+ cp /path/to/myMovie.mov .
55
+
56
+ make docker-convert args="-i myMovie.mov -o myMovie.gif"
57
+ ```
58
+
59
+ See Dockerfile and Makefile for how it works.
60
+
61
+ ### With Vagrant
62
+
63
+ If you have Vagrant and Virtualbox already installed, this is both faster and cleaner than downloading and compiling all the dependencies in OS X. To install, simply do the following:
64
+
65
+ ```
66
+ vagrant up
67
+ ```
68
+
69
+ The easiest way to use it is to copy your image to screengif project directory (shared in the VM under /vagrant), and run the following:
70
+
71
+ ```
72
+ cp ~/screencast.mov ./screencast.mov
73
+ vagrant ssh -- '/vagrant/screengif.rb --input /vagrant/screencast.mov --output /vagrant/output/screencast.gif'
74
+ ls ./output/screencast.gif # should exist!
75
+
76
+ # when finished, destroy the VM
77
+ vagrant destroy -f
78
+ ```
79
+
80
+ ### On OSX, with homebrew
81
+
82
+ The following works with OS X and homebrew, assuming you have ruby 1.9.2+:
83
+
84
+ You may need to install brew-cask: https://github.com/phinze/homebrew-cask
85
+
86
+ ```bash
87
+ git clone https://github.com/dergachev/screengif.git
88
+ cd screengif
89
+
90
+ # x-quartz is a dependency for gifsicle, no longer installed starting on 10.8
91
+ brew cask install xquartz
92
+ open /opt/homebrew-cask/Caskroom/xquartz/2.7.7/XQuartz.pkg # runs the XQuartz installer
93
+
94
+ brew install ffmpeg imagemagick gifsicle
95
+ gem install rmagick
96
+ ```
97
+
98
+ ## Tips
99
+
100
+ See https://gist.github.com/dergachev/4627207#os-x-screencast-to-animated-gif
101
+ for a guide on how to use Quicktime Player to record a screencast on OS X.
102
+ Keep in mind that other tools (like Screenflow) produce better video quality.
103
+
104
+ If you install [dropbox-screenshots](https://github.com/dergachev/dropbox-screenshots),
105
+ the following will automatically upload your new gif to Dropbox:
106
+
107
+ cp out.gif ~/Dropbox/Public/screenshots
108
+
109
+ ## Resources
110
+
111
+ See [DEVNOTES](https://github.com/dergachev/screengif/blob/master/DEVNOTES.md)
@@ -0,0 +1,27 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure("2") do |config|
5
+ config.vm.box = "precise64"
6
+
7
+ # config.vm.provision :shell, :inline => "apt-get install -y vim curl git"
8
+
9
+ config.vm.provision :shell, :inline => <<-EOH
10
+ apt-get update
11
+ apt-get install -y ffmpeg gifsicle imagemagick libmagickwand-dev
12
+ apt-get -y install ruby1.9.1 ruby1.9.1-dev
13
+ gem install bundler --no-rdoc --no-ri
14
+ cd /vagrant
15
+ bundle install
16
+ EOH
17
+
18
+ # test that everything is installed correctly by generating ./output/demo.gif
19
+ config.vm.provision :shell, :inline => <<-EOH
20
+ cd /vagrant
21
+ test -f ./output/demo.gif && exit 0 # ensures this script runs just once
22
+ echo "Testing deployment by converting ./demo.mov to ./output/demo.gif"
23
+ mkdir -p ./output
24
+ # vagrant colors stderr red (undesirable), so redirect it to stdout
25
+ ./screengif.rb --input demo.mov --output ./output/demo.gif 2>&1
26
+ EOH
27
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # when run as gem, $0 is /usr/local/bin/screengif not this file
4
+ if $0 == __FILE__
5
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
6
+ end
7
+
8
+ require 'screengif'
9
+
10
+ Screengif::start
Binary file
Binary file
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'RMagick'
4
+ include Magick
5
+
6
+ require 'screengif/draw_progressbar.rb'
7
+ require 'screengif/options.rb'
8
+ require 'screengif/util.rb'
9
+
10
+ module Screengif
11
+ def self.call_ffmpeg(input_file, options, verbose)
12
+ ffmpeg_loglevel = verbose ? 'verbose' : 'warning'
13
+ if options.framerate
14
+ ffmpeg_framerate = "-r #{options.framerate}"
15
+ end
16
+
17
+ if options.max_width || options.max_height
18
+ options.max_width ||= "-1"
19
+ options.max_height ||= "-1"
20
+ ffmpeg_resize = "-vf scale=#{options.max_width}:#{options.max_height} -sws_flags lanczos"
21
+ end
22
+ # TODO: error handling
23
+ return `ffmpeg -i '#{input_file}' -loglevel #{ffmpeg_loglevel} #{ffmpeg_framerate} #{ffmpeg_resize} -f image2pipe -vcodec ppm - `
24
+ end
25
+
26
+ def self.call_gifsicle(data)
27
+ $stderr.puts "Filtering output through gifsicle" if $verbose
28
+ # TODO: error handling
29
+ result = ''
30
+ # popen is for system calls that require setting STDIN
31
+ IO.popen('gifsicle --loop --optimize=3 --multifile -', 'r+') do |f|
32
+ f.write(data)
33
+ f.close_write
34
+ result = f.read
35
+ end
36
+ return result
37
+ end
38
+
39
+ def self.handle_input(input_file, options, optionparser)
40
+ if (input_file)
41
+ $stderr.puts "Running ffmpeg with #{input_file}" if $verbose
42
+ input = Screengif::call_ffmpeg(input_file, options, $verbose)
43
+ elsif !$stdin.tty? # we are being piped to
44
+ $stderr.puts "Reading input from STDIN." if $verbose
45
+ input = STDIN.read
46
+ else
47
+ $stderr.puts "No input file available."
48
+ puts optionparser
49
+ exit 1
50
+ end
51
+ return input
52
+ end
53
+
54
+ def self.handle_output(output_file, output, optionparser)
55
+ if (output_file)
56
+ File.open(output_file, 'w') do |f|
57
+ f.puts output
58
+ end
59
+ elsif !STDOUT.tty?
60
+ $stderr.puts "Sending output to STDOUT" if $verbose
61
+ puts output
62
+ else
63
+ $stderr.puts "Error: No output destination available."
64
+ puts optionparser
65
+ exit 1
66
+ end
67
+ end
68
+
69
+ def self.start
70
+ options,optionparser = Screengif::Options.parse(ARGV)
71
+ $startTime = Time.now
72
+
73
+ input = handle_input(options.input_file, options, optionparser)
74
+ canvas = ImageList.new.from_blob(input)
75
+
76
+ if (!options.no_coalesce)
77
+ $stderr.puts "Beginning imagemagick coalescing..." if $verbose
78
+ canvas = canvas.coalesce()
79
+ $stderr.puts "Coalescing completed" if $verbose
80
+ end
81
+
82
+ statusPrinter = Screengif::StatusPrinter.new($stderr)
83
+ canvas.each_with_index do |img,index|
84
+ statusPrinter.printText("Processing image: #{index+1}/#{canvas.length}")
85
+ img.delay = (index + 1 == canvas.length) ? options.delay_last : options.delay
86
+ img.format = 'GIF'
87
+
88
+ if options.fuzz.to_i > 0
89
+ # when run as a gem, setting img.fuzz="5%" throws a wierd error; so we do this instead
90
+ # img.fuzz = "#{img.fuzz}%"
91
+ img.fuzz = QuantumRange * options.fuzz.to_i / 100.0
92
+ end
93
+ unless options.nocontrast
94
+ img = img.contrast(true)
95
+ img = img.white_threshold(QuantumRange * 0.99)
96
+ # img = img.level(QuantumRange * 0.05, QuantumRange * 0.95)
97
+ end
98
+ Screengif::DrawProgressbar.draw(img, (index.to_f+1)/canvas.length) if (options.progressbar)
99
+ canvas[index] = img
100
+ end
101
+ statusPrinter.done
102
+
103
+ # see http://stackoverflow.com/questions/958681/how-to-deal-with-memory-leaks-in-rmagick-in-ruby
104
+ GC.start
105
+
106
+ # Reduce down to 256 colors (as required by GIF), disable dithering (equivalent to +dither)
107
+ $stderr.puts "Beginning quantization... (takes a while)" if $verbose
108
+ canvas = canvas.quantize(256, RGBColorspace, NoDitherMethod)
109
+ $stderr.puts "Quantization completed." if $verbose
110
+
111
+ $stderr.puts "Beginning rmagick OptimizePlusLayer..." if $verbose
112
+ canvas = canvas.optimize_layers(OptimizePlusLayer)
113
+ $stderr.puts "Beginning rmagick OptimizeTransLayer..." if $verbose
114
+ canvas = canvas.optimize_layers(OptimizeTransLayer)
115
+
116
+ $stderr.puts "Rmagick processing completed. Outputting results..." if $verbose
117
+ output = canvas.to_blob
118
+
119
+ GC.start
120
+
121
+ output = Screengif::call_gifsicle(output) unless (options.no_gifsicle)
122
+
123
+ handle_output(options.output_file, output, optionparser)
124
+ Screengif::ConversionStats.print(options.input_file, options.output_file, input, output)
125
+ end
126
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Screengif
4
+ class DrawProgressbar
5
+ def self.draw(img,ratio)
6
+ wid = img.columns() - 3
7
+ ht = img.rows() - 3
8
+ rectWid = 60
9
+ rectHt = 20
10
+
11
+ progressbar = Draw.new
12
+
13
+ progressbar
14
+ .fill('white')
15
+ .stroke('black')
16
+ .draw(img)
17
+ .rectangle(wid-rectWid,ht-rectHt,wid,ht)
18
+ progressbar
19
+ .fill('black')
20
+ .pointsize(12)
21
+ .stroke('transparent')
22
+ .font_weight(BoldWeight)
23
+ .gravity(NorthWestGravity)
24
+ .text(wid-rectWid+4,ht-rectHt+5,"screengif")
25
+ progressbar
26
+ .fill('black')
27
+ .stroke('transparent')
28
+ .rectangle(wid-rectWid,ht-rectHt,wid-rectWid*(1-ratio),ht)
29
+ progressbar.draw(img)
30
+
31
+ maskedDraw = Draw.new
32
+ maskedDraw.define_clip_path('clip') {
33
+ maskedDraw
34
+ .rectangle(wid-rectWid,ht-rectHt,wid-rectWid*(1-ratio),ht)
35
+ }
36
+ maskedDraw.push
37
+ maskedDraw.clip_path('clip')
38
+ maskedDraw
39
+ .fill('white')
40
+ .pointsize(12)
41
+ .stroke('transparent')
42
+ .font_weight(BoldWeight)
43
+ .gravity(NorthWestGravity)
44
+ .text(wid-rectWid+4,ht-rectHt+5,"screengif")
45
+ maskedDraw.pop
46
+ maskedDraw.draw(img)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'ostruct'
5
+ require 'pp'
6
+
7
+ $verbose = false
8
+
9
+ module Screengif
10
+ class Options
11
+ def self.parse(args)
12
+ options = OpenStruct.new
13
+
14
+ options.framerate = 5
15
+ options.delay = 10
16
+ options.delay_last = 50
17
+ options.no_coalesce = false
18
+ options.progressbar = false
19
+ options.input_file = nil
20
+ options.output_file = nil
21
+ options.no_gifsicle = false
22
+ options.fuzz = 5
23
+
24
+ # options.ffmpeg_inputfile = nil
25
+
26
+ optionparser = OptionParser.new do |opts|
27
+ opts.banner = "screengif.rb - Convert your screencast into a gif.\n" +
28
+ "Usage:\n" +
29
+ "\tscreengif.rb [options] [--input FILENAME.mov] [--output OUTPUTFILE.gif]\n" +
30
+ "Examples:\n" +
31
+ "\t./screengif.rb --input demo.mov --output out.gif\n" +
32
+ "\tcat somefile.gif | ./screengif.rb --progressbar --framerate 10 --delay 50 --delay-last 5 > out.gif\n"
33
+
34
+ opts.separator ""
35
+ opts.separator "Specific options:"
36
+
37
+ opts.on("-i", "--input FILENAME.mov", "Use ffmpeg to convert FILENAME.mov into PPM image stream and process results.",
38
+ "If missing, will process PPM or GIF image stream from STDIN.") do |filename|
39
+ if (File.exists?(filename))
40
+ options.input_file = filename
41
+ options.no_coalesce = true # ffmpeg's ppm output is already coalesced
42
+ else
43
+ $stderr.puts "Unable to open filename: #{filename}"
44
+ puts opts
45
+ exit 1
46
+ end
47
+ end
48
+ opts.on("-o", "--output FILENAME.gif", "Output resulting GIF data to FILENAME.gif. (defaults to STDOUT).") do |filename|
49
+ options.output_file = filename
50
+ end
51
+
52
+ opts.on("-d", "--delay MS", Integer, "Animation frame delay, in tens of ms. (default: 10)") do |tens_of_ms|
53
+ options.delay = tens_of_ms.to_i
54
+ end
55
+
56
+ opts.on("-p", "--progressbar", "Overlay progress bar on the animation.") do
57
+ options.progressbar = true
58
+ end
59
+
60
+ opts.on("-d", "--delay MS", Integer, "Animation frame delay, in tens of ms. (default: 10)") do |tens_of_ms|
61
+ options.delay = tens_of_ms.to_i
62
+ end
63
+
64
+ opts.on("--delay-last MS", Integer, "Animation frame delay of last frame, in tens of ms. (default: 50)") do |tens_of_ms|
65
+ options.delay_last = tens_of_ms.to_i
66
+ end
67
+
68
+ opts.on("-r", "--framerate FPS", Integer, "Specify amount of frames per second to keep. (default: 5)") do |fps|
69
+ options.framerate = fps.to_i
70
+ end
71
+
72
+ opts.on("-w", "--max-width PIXELS", Integer, "Output image max width, in pixels.") do |pixels|
73
+ options.max_width = pixels.to_i
74
+ end
75
+
76
+ opts.on("--max-height PIXELS", Integer, "Output image max height, in pixels.") do |pixels|
77
+ options.max_height = pixels.to_i
78
+ end
79
+
80
+ opts.on("--no-contrast", "Skip increasing contrast using imagemagick.") do
81
+ options.nocontrast = true
82
+ end
83
+
84
+ opts.on("-f", "--fuzz PERCENT", Integer, "Imagemagick fuzz factor for color reduction. (default: 5%)") do |fuzz|
85
+ options.fuzz = fuzz.to_i
86
+ end
87
+
88
+ opts.on("--no-coalesce", "Skip Magick::ImageList#coalesce() if input doesn't need it.") do
89
+ options.no_coalesce = true
90
+ end
91
+
92
+ opts.on("--no-gifsicle", "Prevent filter the output through gifsicle. Greatly increases output file size.") do
93
+ options.no_gifsicle = true
94
+ end
95
+
96
+ # Boilerplate
97
+ opts.on_tail("-h", "--help", "Show this message") do
98
+ puts opts
99
+ exit
100
+ end
101
+ opts.on_tail("-v", "--verbose", "Verbose output") do
102
+ $verbose = true
103
+ end
104
+ opts.on_tail("--version", "Show version") do
105
+ puts "0.1"
106
+ exit
107
+ end
108
+ end
109
+ optionparser.parse!(args)
110
+ return options, optionparser
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ module Screengif
5
+ class StatusPrinter
6
+ # inspired by http://stackoverflow.com/a/6679572/9621
7
+ def initialize(stream)
8
+ @previous_size = 0
9
+ @stream = stream || $stdout
10
+ end
11
+
12
+ def printText(text)
13
+ if @previous_size > 0
14
+ @stream.print "\033[#{@previous_size}D"
15
+ @stream.print(" " * @previous_size)
16
+ @stream.print "\033[#{@previous_size}D"
17
+ end
18
+ @stream.print text
19
+ @stream.flush
20
+ @previous_size = text.gsub(/\e\[\d+m/,"").size
21
+ end
22
+
23
+ def done()
24
+ @previous_size = 0
25
+ @stream.print "\n"
26
+ end
27
+ end
28
+
29
+ class ConversionStats
30
+ def self.print(input_file, output_file, input, output)
31
+ $stderr.puts "Conversion completed in #{Time.now - $startTime} seconds."
32
+ if input_file # ffmpeg
33
+ # Duration: 00:00:04.28, start: 0.010333, bitrate: 11225 kb/s
34
+ duration = (`ffmpeg -i '#{input_file}' 2>&1 | grep Duration`).gsub(/^.*Duration:\s*([^,]+),.*$/, '\1').gsub("\n",'')
35
+
36
+ input_filesize = `ls -lh '#{input_file}' | awk '{print $5}'`.gsub("\n",'')
37
+ $stderr.puts "Input: #{input_file} (#{duration}, #{input_filesize})"
38
+ else # piped input
39
+ input_contentsize = (input.bytesize.to_f / 2**10).to_i().to_s + "K"
40
+ $stderr.puts "Input: STDIN (#{input_contentsize})"
41
+ end
42
+ if output_file
43
+ output_filesize = `ls -lh '#{output_file}' | awk '{print $5}'`.gsub("\n",'')
44
+ $stderr.puts "Output: '#{output_file}' (#{output_filesize})"
45
+ else # piped output
46
+ output_contentsize = (output.bytesize.to_f / 2**10).to_i().to_s + "K"
47
+ $stderr.puts "Output: STDOUT (#{output_contentsize})"
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "screengif"
5
+ spec.version = "0.0.1"
6
+ spec.authors = "Alex Dergachev"
7
+ spec.email = "alex@evolvingweb.ca"
8
+ spec.summary = 'Script to convert mov files to animated gifs.'
9
+ spec.description = 'Wrapper on ffmpeg and imagemagick to convert .mov to .gif'
10
+ spec.homepage = 'https://github.com/dergachev/screengif'
11
+ spec.license = "MIT"
12
+
13
+ spec.files = `git ls-files`.split($/)
14
+ spec.bindir = 'bin'
15
+ spec.executables = 'screengif'
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_path = 'lib'
18
+
19
+ spec.add_development_dependency "bundler"
20
+ spec.add_development_dependency "rake"
21
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: screengif
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Dergachev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Wrapper on ffmpeg and imagemagick to convert .mov to .gif
47
+ email: alex@evolvingweb.ca
48
+ executables:
49
+ - screengif
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - DEVNOTES.md
55
+ - Dockerfile
56
+ - Gemfile
57
+ - Makefile
58
+ - README.md
59
+ - Vagrantfile
60
+ - bin/screengif
61
+ - demo.gif
62
+ - demo.mov
63
+ - lib/screengif.rb
64
+ - lib/screengif/draw_progressbar.rb
65
+ - lib/screengif/options.rb
66
+ - lib/screengif/util.rb
67
+ - screengif.gemspec
68
+ homepage: https://github.com/dergachev/screengif
69
+ licenses:
70
+ - MIT
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.23
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Script to convert mov files to animated gifs.
93
+ test_files: []