transcode 1.0.4 → 1.0.6
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 +4 -4
- data/LICENSE +3 -10
- data/README.adoc +140 -0
- data/bin/transcode +8 -5
- data/lib/transcode/configurator.rb +19 -17
- data/lib/transcode/reporter.rb +6 -4
- data/lib/transcode/string.rb +14 -0
- data/lib/transcode/timer.rb +40 -0
- data/lib/transcode/transcoder.rb +10 -8
- data/lib/transcode/utils.rb +8 -53
- data/lib/transcode/version.rb +5 -4
- data/lib/transcode.rb +3 -2
- metadata +31 -72
- data/Gemfile +0 -14
- data/README.md +0 -76
- data/Rakefile +0 -10
- data/appveyor.yml +0 -26
- data/transcode.gemspec +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f440499f81a31db9e875f0cddc6dc09287eab75d505d467385274a903ee77504
|
|
4
|
+
data.tar.gz: 40097203d275461d347bf4f137553e34ccd0f9cb64376a0d6f6d7f488fe5aec2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a00be08b5cd28da92fc2314d3ce707552fbf0e55f096c139c7d7c41a95d8429e959b82cdcbebf293d40ff04fb42d255379bfd5f105bc68adefdb52094ef0aa6
|
|
7
|
+
data.tar.gz: b8d823e3aa6c74c3deb877d001fce5e569c890dfd17b3272e0214f4b2c3609e04f6b50667e4e53727f62a4c9b98fd3f91b02e0dd5095ea8ca49d6e8573b1932d
|
data/LICENSE
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
Copyright 2020
|
|
1
|
+
Copyright 2020-2026 David Rabkin
|
|
2
2
|
|
|
3
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
-
purpose with or without fee is hereby granted.
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
|
|
5
4
|
|
|
6
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
7
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
8
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
9
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
10
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
11
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
12
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
5
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.adoc
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Settings:
|
|
2
|
+
:toc: macro
|
|
3
|
+
:!toc-title:
|
|
4
|
+
// URLs:
|
|
5
|
+
:img-gem: https://badge.fury.io/rb/transcode.svg
|
|
6
|
+
:img-hoc: https://hitsofcode.com/github/rdavid/transcode?branch=master&label=hits%20of%20code
|
|
7
|
+
:img-license: https://img.shields.io/github/license/rdavid/transcode?color=blue&labelColor=gray&logo=freebsd&logoColor=lightgray&style=flat
|
|
8
|
+
:img-rake: https://github.com/rdavid/transcode/actions/workflows/rake.yml/badge.svg
|
|
9
|
+
:url-cv: http://cv.rabkin.co.il
|
|
10
|
+
:url-gem: https://badge.fury.io/rb/transcode
|
|
11
|
+
:url-hoc: https://hitsofcode.com/view/github/rdavid/transcode?branch=master
|
|
12
|
+
:url-license: https://github.com/rdavid/transcode/blob/master/LICENSES/0BSD.txt
|
|
13
|
+
:url-melton: https://github.com/lisamelton/video_transcoding
|
|
14
|
+
:url-rake: https://github.com/rdavid/transcode/actions/workflows/rake.yml
|
|
15
|
+
:url-reuse: https://github.com/fsfe/reuse-action
|
|
16
|
+
:url-requirements: https://github.com/lisamelton/video_transcoding/blob/master/README.md?ts=2#requirements
|
|
17
|
+
:url-ruby: https://www.ruby-lang.org/en/documentation/installation
|
|
18
|
+
:url-video: https://github.com/lisamelton/video_transcoding
|
|
19
|
+
:url-vale: https://vale.sh
|
|
20
|
+
:url-yamllint: https://github.com/adrienverge/yamllint
|
|
21
|
+
|
|
22
|
+
= Transcode
|
|
23
|
+
|
|
24
|
+
image:{img-rake}[rake,link={url-rake}]
|
|
25
|
+
image:{img-gem}[gem version,link={url-gem}]
|
|
26
|
+
image:{img-hoc}[hits of code,link={url-hoc}]
|
|
27
|
+
image:{img-license}[license,link={url-license}]
|
|
28
|
+
|
|
29
|
+
toc::[]
|
|
30
|
+
|
|
31
|
+
== About
|
|
32
|
+
|
|
33
|
+
Transcode is a command-line tool that converts whole directories of video
|
|
34
|
+
files in one run.
|
|
35
|
+
It wraps {url-melton}[Lisa Melton's] {url-video}[Video Transcoding],
|
|
36
|
+
which converts one file per invocation, and applies the same workflow
|
|
37
|
+
to every video in a directory with a single command.
|
|
38
|
+
|
|
39
|
+
Transcode can:
|
|
40
|
+
|
|
41
|
+
* Convert an entire directory to `.m4v` in a single run.
|
|
42
|
+
* Select the main audio and burned-in subtitle stream for each file.
|
|
43
|
+
* Extract audio to `.mp3`.
|
|
44
|
+
* Scan files to list their available audio and subtitle streams.
|
|
45
|
+
* Print a summary table of the results.
|
|
46
|
+
|
|
47
|
+
It recognizes these input formats: `avi`, `flv`, `m2ts`, `m4v`, `mkv`,
|
|
48
|
+
`mp4`, `mpg`, `mpeg`, `mov`, `ts`, `webm`, `vob`, and `wmv`.
|
|
49
|
+
|
|
50
|
+
== Installation
|
|
51
|
+
|
|
52
|
+
Transcode ships as a Ruby gem and requires Ruby 3.2 or later.
|
|
53
|
+
It runs on macOS, GNU/Linux, Windows, and any other system Ruby
|
|
54
|
+
supports.
|
|
55
|
+
See {url-ruby}[Installing Ruby] if Ruby 3.2+ is not available on your
|
|
56
|
+
platform.
|
|
57
|
+
|
|
58
|
+
Install with:
|
|
59
|
+
|
|
60
|
+
[,sh]
|
|
61
|
+
----
|
|
62
|
+
gem install transcode
|
|
63
|
+
----
|
|
64
|
+
|
|
65
|
+
== Updating
|
|
66
|
+
|
|
67
|
+
Update with:
|
|
68
|
+
|
|
69
|
+
[,sh]
|
|
70
|
+
----
|
|
71
|
+
gem update transcode
|
|
72
|
+
----
|
|
73
|
+
|
|
74
|
+
== Requirements
|
|
75
|
+
|
|
76
|
+
See Video Transcoding's {url-requirements}[requirements] for external
|
|
77
|
+
dependencies.
|
|
78
|
+
|
|
79
|
+
== Usage
|
|
80
|
+
|
|
81
|
+
[,sh]
|
|
82
|
+
----
|
|
83
|
+
transcode [options]
|
|
84
|
+
-a, --act Perform actual encoding.
|
|
85
|
+
-u, --aud aud Audio stream numbers.
|
|
86
|
+
-d, --dir dir Source directory to transcode.
|
|
87
|
+
-m, --mp3 Convert files to MP3.
|
|
88
|
+
-o, --out out Output directory.
|
|
89
|
+
-s, --sca Scan files in the directory.
|
|
90
|
+
-t, --sub sub Subtitle stream numbers.
|
|
91
|
+
-i, --tit tit Specific title number.
|
|
92
|
+
-v, --version Show version.
|
|
93
|
+
-w, --wid wid Width of the table.
|
|
94
|
+
----
|
|
95
|
+
|
|
96
|
+
Transcode performs a dry run by default.
|
|
97
|
+
It prints the commands it would run and a summary table without changing any
|
|
98
|
+
files.
|
|
99
|
+
Pass `--act` to start the encoding.
|
|
100
|
+
|
|
101
|
+
Without `--dir` and `--out`, Transcode reads from and writes to the current
|
|
102
|
+
directory.
|
|
103
|
+
The `--aud` and `--sub` options take comma-separated stream numbers, either
|
|
104
|
+
one value applied to every file or one value per file.
|
|
105
|
+
|
|
106
|
+
== Examples
|
|
107
|
+
|
|
108
|
+
Scan the source directory to inspect the available audio and subtitle
|
|
109
|
+
streams:
|
|
110
|
+
|
|
111
|
+
[,sh]
|
|
112
|
+
----
|
|
113
|
+
transcode --sca --dir [source]
|
|
114
|
+
----
|
|
115
|
+
|
|
116
|
+
Transcode three files from `[source]` to `[destination]` with the selected
|
|
117
|
+
audio and subtitle streams.
|
|
118
|
+
Add `--act` once the plan looks right:
|
|
119
|
+
|
|
120
|
+
[,sh]
|
|
121
|
+
----
|
|
122
|
+
transcode \
|
|
123
|
+
--act \
|
|
124
|
+
--aud 1,3,1 \
|
|
125
|
+
--dir [source] \
|
|
126
|
+
--out [destination] \
|
|
127
|
+
--sub 2,1,3
|
|
128
|
+
----
|
|
129
|
+
|
|
130
|
+
Extract the audio of every file in the current directory to `.mp3`:
|
|
131
|
+
|
|
132
|
+
[,sh]
|
|
133
|
+
----
|
|
134
|
+
transcode --mp3 --act
|
|
135
|
+
----
|
|
136
|
+
|
|
137
|
+
== License
|
|
138
|
+
|
|
139
|
+
`transcode` is copyright {url-cv}[David Rabkin] and available under a
|
|
140
|
+
{url-license}[Zero-Clause BSD license].
|
data/bin/transcode
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# vi:
|
|
5
|
-
#
|
|
4
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
5
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
6
|
+
# SPDX-License-Identifier: 0BSD
|
|
6
7
|
|
|
7
|
-
require 'pidfile'
|
|
8
8
|
require_relative '../lib/transcode'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
Transcode::Transcoder.new.do
|
|
10
|
+
begin
|
|
11
|
+
Transcode::Transcoder.new.do
|
|
12
|
+
rescue StandardError => e
|
|
13
|
+
abort "transcode: #{e.message}"
|
|
14
|
+
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
7
|
require 'optparse'
|
|
8
|
+
require_relative 'string'
|
|
7
9
|
|
|
8
10
|
module Transcode
|
|
9
11
|
# Handles input parameters.
|
|
@@ -11,19 +13,19 @@ module Transcode
|
|
|
11
13
|
attr_reader :files
|
|
12
14
|
|
|
13
15
|
DIC = [
|
|
14
|
-
['-a', '--act', '
|
|
15
|
-
['-s', '--sca', 'Scans files at the directory.', nil, :sca],
|
|
16
|
-
['-m', '--mp3', 'Converts files to mp3.', nil, :mp3],
|
|
17
|
-
['-d', '--dir dir', 'Directory to transcode.', String, :dir],
|
|
18
|
-
['-i', '--tit tit', 'Specific title by number.', Array, :tit],
|
|
19
|
-
['-o', '--out out', 'Directory to output.', String, :out],
|
|
16
|
+
['-a', '--act', 'Perform actual encoding.', nil, :act],
|
|
20
17
|
['-u', '--aud aud', 'Audio stream numbers.', Array, :aud],
|
|
18
|
+
['-d', '--dir dir', 'Source directory to transcode.', String, :dir],
|
|
19
|
+
['-m', '--mp3', 'Convert files to MP3.', nil, :mp3],
|
|
20
|
+
['-o', '--out out', 'Output directory.', String, :out],
|
|
21
|
+
['-s', '--sca', 'Scan files in the directory.', nil, :sca],
|
|
21
22
|
['-t', '--sub sub', 'Subtitle stream numbers.', Array, :sub],
|
|
23
|
+
['-i', '--tit tit', 'Specific title number.', Array, :tit],
|
|
22
24
|
['-w', '--wid wid', 'Width of the table.', Integer, :wid]
|
|
23
25
|
].freeze
|
|
24
|
-
EXT = %
|
|
26
|
+
EXT = %w[
|
|
25
27
|
avi flv m2ts m4v mkv mp4 mpg mpeg mov ts webm vob wmv
|
|
26
|
-
].
|
|
28
|
+
].join(',').freeze
|
|
27
29
|
|
|
28
30
|
def add(opt)
|
|
29
31
|
opt.on('-v', '--version', 'Show version.') do
|
|
@@ -53,8 +55,7 @@ module Transcode
|
|
|
53
55
|
@files = Dir.glob("#{dir}/*.{#{EXT}}").select { |f| File.file? f }
|
|
54
56
|
sub = !mp3?
|
|
55
57
|
@files += Dir.glob("#{dir}/*").select { |f| File.directory? f } if sub
|
|
56
|
-
@files.sort_by!
|
|
57
|
-
@files.sort_by!(&:swapcase)
|
|
58
|
+
@files.sort_by! { |f| f.swapcase.naturalized }
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def validate
|
|
@@ -64,19 +65,19 @@ module Transcode
|
|
|
64
65
|
validate_tit
|
|
65
66
|
validate_val(aud, :aud)
|
|
66
67
|
validate_val(sub, :sub)
|
|
67
|
-
raise "Width of the table
|
|
68
|
+
raise "Width of the table must exceed 14 characters: #{wid}." if wid < 15
|
|
68
69
|
end
|
|
69
70
|
|
|
70
71
|
def validate_dir(dir, isw)
|
|
71
72
|
raise "#{dir}: No such directory." unless File.directory?(dir)
|
|
72
73
|
|
|
73
74
|
err = isw ? File.writable?(dir) : File.readable?(dir)
|
|
74
|
-
raise "#{
|
|
75
|
+
raise "#{dir}: Permission denied." unless err
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def validate_fil
|
|
78
79
|
bad = files.reject { |f| File.readable?(f) }
|
|
79
|
-
raise "#{dir}
|
|
80
|
+
raise "#{dir} has no #{EXT} files or directories." if files.empty?
|
|
80
81
|
raise "#{bad.join(',')}: Permission denied." unless bad.empty?
|
|
81
82
|
end
|
|
82
83
|
|
|
@@ -100,7 +101,7 @@ module Transcode
|
|
|
100
101
|
if s == 1
|
|
101
102
|
@options[tag] = Array.new(f, val.first)
|
|
102
103
|
else
|
|
103
|
-
raise "#{tag}
|
|
104
|
+
raise "#{tag} count #{s} doesn't match file count #{f}." unless s == f
|
|
104
105
|
end
|
|
105
106
|
end
|
|
106
107
|
|
|
@@ -136,9 +137,10 @@ module Transcode
|
|
|
136
137
|
@options[:sub]
|
|
137
138
|
end
|
|
138
139
|
|
|
140
|
+
# Returns the table width, falling back to the terminal width when the
|
|
141
|
+
# option is not set.
|
|
139
142
|
def wid
|
|
140
143
|
if @options[:wid].nil?
|
|
141
|
-
# Reads current terminal width.
|
|
142
144
|
wid = `tput cols`
|
|
143
145
|
wid.to_s.empty? ? 79 : wid.to_i
|
|
144
146
|
else
|
data/lib/transcode/reporter.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
7
|
require 'terminal-table'
|
|
8
|
+
require_relative 'timer'
|
|
7
9
|
require_relative 'utils'
|
|
8
10
|
|
|
9
11
|
module Transcode
|
|
10
|
-
# Formats and prints
|
|
12
|
+
# Formats and prints the summary table.
|
|
11
13
|
class Reporter
|
|
12
14
|
def initialize(act, tit, wid)
|
|
13
15
|
@act = act
|
|
@@ -63,7 +65,7 @@ module Transcode
|
|
|
63
65
|
def stat
|
|
64
66
|
out = ''
|
|
65
67
|
@sta.each do |k, v|
|
|
66
|
-
out +=
|
|
68
|
+
out += " #{v} #{k}," if v.positive?
|
|
67
69
|
end
|
|
68
70
|
out.chop
|
|
69
71
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
6
|
+
|
|
7
|
+
# Adds a natural sort method. It converts a string such as "Filename 10"
|
|
8
|
+
# into an array with floats in place of numbers, ["Filename", 10.0], as
|
|
9
|
+
# suggested in https://stackoverflow.com/q/4078906.
|
|
10
|
+
class String
|
|
11
|
+
def naturalized
|
|
12
|
+
scan(/[^\d.]+|[\d.]+/).map { |f| f.match?(/\d+(\.\d+)?/) ? f.to_f : f }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
6
|
+
|
|
7
|
+
# Measures elapsed time and reports it as a humanized string.
|
|
8
|
+
class Timer
|
|
9
|
+
@less_sec = 'less than a second'
|
|
10
|
+
class << self
|
|
11
|
+
attr_reader :less_sec
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
DIC = [
|
|
15
|
+
[60, :seconds, :second],
|
|
16
|
+
[60, :minutes, :minute],
|
|
17
|
+
[24, :hours, :hour],
|
|
18
|
+
[1000, :days, :day]
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@sta = Time.now
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def read
|
|
26
|
+
humanize(Time.now - @sta)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def humanize(sec)
|
|
30
|
+
return '' if sec.nil?
|
|
31
|
+
return Timer.less_sec if sec < 1
|
|
32
|
+
|
|
33
|
+
DIC.filter_map do |cnt, nms, nm1|
|
|
34
|
+
next if sec <= 0
|
|
35
|
+
|
|
36
|
+
sec, n = sec.divmod(cnt)
|
|
37
|
+
"#{n.to_i} #{n.to_i == 1 ? nm1 : nms}"
|
|
38
|
+
end.compact.reverse.join(' ')
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/transcode/transcoder.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
7
|
require 'English'
|
|
7
8
|
require 'shellwords'
|
|
@@ -16,7 +17,8 @@ module Transcode
|
|
|
16
17
|
@rep = Reporter.new(@cfg.act?, "#{@cfg.dir} -> #{@cfg.out}", @cfg.wid)
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
# Runs command and prints output
|
|
20
|
+
# Runs a command and prints its output as it arrives. Returns true on
|
|
21
|
+
# success.
|
|
20
22
|
def run(cmd)
|
|
21
23
|
cmd += ' 2>&1'
|
|
22
24
|
puts "Run: #{cmd}."
|
|
@@ -27,8 +29,8 @@ module Transcode
|
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def m4v_cmd(file, aud, sub, tit)
|
|
30
|
-
c = 'transcode-video --m4v --no-log --preset veryslow'\
|
|
31
|
-
"
|
|
32
|
+
c = 'transcode-video --m4v --no-log --preset veryslow ' \
|
|
33
|
+
"--output #{@cfg.out}"
|
|
32
34
|
unless tit == '0'
|
|
33
35
|
c += "/#{File.basename(file.shellescape)}-#{tit}.m4v"
|
|
34
36
|
c += " --title #{tit}"
|
|
@@ -38,7 +40,7 @@ module Transcode
|
|
|
38
40
|
c + " #{file.shellescape}"
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
# Converts
|
|
43
|
+
# Converts file, audio, subtitle, and title arrays into an array:
|
|
42
44
|
# [ file1 [ aud1, sub1, tit1 ] ]
|
|
43
45
|
# [ file2 [ aud2, sub2, tit2 ] ]
|
|
44
46
|
def data
|
|
@@ -54,7 +56,7 @@ module Transcode
|
|
|
54
56
|
|
|
55
57
|
def mp3_cmd(file)
|
|
56
58
|
file = file.shellescape
|
|
57
|
-
"ffmpeg -i #{file} -vn -ar 44100 -ac 2 -ab 192k -f mp3 "\
|
|
59
|
+
"ffmpeg -i #{file} -vn -ar 44100 -ac 2 -ab 192k -f mp3 " \
|
|
58
60
|
"#{@cfg.out}/#{File.basename(file, '.*')}.mp3"
|
|
59
61
|
end
|
|
60
62
|
|
|
@@ -62,7 +64,7 @@ module Transcode
|
|
|
62
64
|
"transcode-video --scan #{file.shellescape}"
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
def do
|
|
67
|
+
def do
|
|
66
68
|
if @cfg.mp3?
|
|
67
69
|
@cfg.files.each { |f| @rep.add(f, @cfg.act? ? run(mp3_cmd(f)) : true) }
|
|
68
70
|
elsif @cfg.sca?
|
data/lib/transcode/utils.rb
CHANGED
|
@@ -1,64 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
require 'ellipsized'
|
|
8
|
+
|
|
9
|
+
# Provides string helpers as class methods.
|
|
7
10
|
class Utils
|
|
8
11
|
@sep = '~'
|
|
9
12
|
class << self
|
|
10
13
|
attr_accessor :sep
|
|
11
|
-
def trim(src, lim)
|
|
12
|
-
return '' if src.nil? || lim.nil?
|
|
13
|
-
return src if src.length <= lim
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
src[0..beg] + @sep + src[-fin..-1]
|
|
15
|
+
def trim(src, lim)
|
|
16
|
+
src.ellipsized(lim, @sep, :center)
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
19
|
end
|
|
21
|
-
|
|
22
|
-
# Returns string with humanized time interval.
|
|
23
|
-
class Timer
|
|
24
|
-
@less_sec = 'less than a second'
|
|
25
|
-
class << self
|
|
26
|
-
attr_reader :less_sec
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
DIC = [
|
|
30
|
-
[60, :seconds, :second],
|
|
31
|
-
[60, :minutes, :minute],
|
|
32
|
-
[24, :hours, :hour],
|
|
33
|
-
[1000, :days, :day]
|
|
34
|
-
].freeze
|
|
35
|
-
|
|
36
|
-
def initialize
|
|
37
|
-
@sta = Time.now
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def read
|
|
41
|
-
humanize(Time.now - @sta)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def humanize(sec)
|
|
45
|
-
return '' if sec.nil?
|
|
46
|
-
return Timer.less_sec if sec < 1
|
|
47
|
-
|
|
48
|
-
DIC.map do |cnt, nms, nm1|
|
|
49
|
-
next if sec <= 0
|
|
50
|
-
|
|
51
|
-
sec, n = sec.divmod(cnt)
|
|
52
|
-
"#{n.to_i} #{n.to_i != 1 ? nms : nm1}"
|
|
53
|
-
end.compact.reverse.join(' ')
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Adds natural sort method. This converts something like "Filename 10" into a
|
|
58
|
-
# simple array with floats in place of numbers [ "Filename", 10.0 ]. See:
|
|
59
|
-
# https://stackoverflow.com/questions/4078906/is-there-a-natural-sort-by-method-for-ruby
|
|
60
|
-
class String
|
|
61
|
-
def naturalized
|
|
62
|
-
scan(/[^\d\.]+|[\d\.]+/).collect { |f| f.match(/\d+(\.\d+)?/) ? f.to_f : f }
|
|
63
|
-
end
|
|
64
|
-
end
|
data/lib/transcode/version.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2020-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
7
|
module Transcode
|
|
7
|
-
VERSION = '1.0.
|
|
8
|
-
DATE = '
|
|
8
|
+
VERSION = '1.0.6'
|
|
9
|
+
DATE = '2026-07-15'
|
|
9
10
|
end
|
data/lib/transcode.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# vi:
|
|
4
|
-
#
|
|
3
|
+
# vi: et lbr sw=2 ts=2 tw=79 wrap
|
|
4
|
+
# SPDX-FileCopyrightText: 2018-2026 David Rabkin
|
|
5
|
+
# SPDX-License-Identifier: 0BSD
|
|
5
6
|
|
|
6
7
|
require_relative 'transcode/transcoder'
|
|
7
8
|
require_relative 'transcode/version'
|
metadata
CHANGED
|
@@ -1,142 +1,101 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: transcode
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Rabkin
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
13
|
+
name: ellipsized
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
|
-
- -
|
|
16
|
+
- - "~>"
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.3
|
|
18
|
+
version: '0.3'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
|
-
- -
|
|
23
|
+
- - "~>"
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.3
|
|
25
|
+
version: '0.3'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: terminal-table
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
|
-
- -
|
|
30
|
+
- - "~>"
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
32
|
+
version: '4.0'
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
|
-
- -
|
|
37
|
+
- - "~>"
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
39
|
+
version: '4.0'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: video_transcoding
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
|
-
- -
|
|
44
|
+
- - "~>"
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.25
|
|
46
|
+
version: '0.25'
|
|
48
47
|
type: :runtime
|
|
49
48
|
prerelease: false
|
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
50
|
requirements:
|
|
52
|
-
- -
|
|
51
|
+
- - "~>"
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.25
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
requirements:
|
|
59
|
-
- - '='
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: 5.18.0
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - '='
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: 5.18.0
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: rake
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - '='
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: 13.0.6
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
-
requirements:
|
|
80
|
-
- - '='
|
|
81
|
-
- !ruby/object:Gem::Version
|
|
82
|
-
version: 13.0.6
|
|
83
|
-
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: rubocop
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - '='
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: 1.50.2
|
|
90
|
-
type: :development
|
|
91
|
-
prerelease: false
|
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
-
requirements:
|
|
94
|
-
- - '='
|
|
95
|
-
- !ruby/object:Gem::Version
|
|
96
|
-
version: 1.50.2
|
|
97
|
-
description: " Transcode is a wraper on Video Transcoding.\n"
|
|
53
|
+
version: '0.25'
|
|
54
|
+
description: |2
|
|
55
|
+
Transcode wraps Lisa Melton's Video Transcoding and converts whole
|
|
56
|
+
directories of video files in one run.
|
|
98
57
|
email: david@rabkin.co.il
|
|
99
58
|
executables:
|
|
100
59
|
- transcode
|
|
101
60
|
extensions: []
|
|
102
61
|
extra_rdoc_files:
|
|
103
62
|
- LICENSE
|
|
104
|
-
- README.
|
|
63
|
+
- README.adoc
|
|
105
64
|
files:
|
|
106
|
-
- Gemfile
|
|
107
65
|
- LICENSE
|
|
108
|
-
- README.
|
|
109
|
-
- Rakefile
|
|
110
|
-
- appveyor.yml
|
|
66
|
+
- README.adoc
|
|
111
67
|
- bin/transcode
|
|
112
68
|
- lib/transcode.rb
|
|
113
69
|
- lib/transcode/configurator.rb
|
|
114
70
|
- lib/transcode/reporter.rb
|
|
71
|
+
- lib/transcode/string.rb
|
|
72
|
+
- lib/transcode/timer.rb
|
|
115
73
|
- lib/transcode/transcoder.rb
|
|
116
74
|
- lib/transcode/utils.rb
|
|
117
75
|
- lib/transcode/version.rb
|
|
118
|
-
- transcode.gemspec
|
|
119
76
|
homepage: https://github.com/rdavid/transcode
|
|
120
77
|
licenses:
|
|
121
78
|
- 0BSD
|
|
122
|
-
metadata:
|
|
123
|
-
|
|
79
|
+
metadata:
|
|
80
|
+
bug_tracker_uri: https://github.com/rdavid/transcode/issues
|
|
81
|
+
homepage_uri: https://github.com/rdavid/transcode
|
|
82
|
+
rubygems_mfa_required: 'true'
|
|
83
|
+
source_code_uri: https://github.com/rdavid/transcode
|
|
124
84
|
rdoc_options: []
|
|
125
85
|
require_paths:
|
|
126
86
|
- lib
|
|
127
87
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
128
88
|
requirements:
|
|
129
|
-
- - "
|
|
89
|
+
- - ">="
|
|
130
90
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '2
|
|
91
|
+
version: '3.2'
|
|
132
92
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
93
|
requirements:
|
|
134
94
|
- - ">="
|
|
135
95
|
- !ruby/object:Gem::Version
|
|
136
96
|
version: '0'
|
|
137
97
|
requirements: []
|
|
138
|
-
rubygems_version: 3.
|
|
139
|
-
signing_key:
|
|
98
|
+
rubygems_version: 3.6.9
|
|
140
99
|
specification_version: 4
|
|
141
|
-
summary:
|
|
100
|
+
summary: Tool to transcode batches of video files
|
|
142
101
|
test_files: []
|
data/Gemfile
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# vi:ts=2 sw=2 tw=79 et lbr wrap
|
|
4
|
-
# Copyright 2020-2023 by David Rabkin
|
|
5
|
-
|
|
6
|
-
source 'https://rubygems.org'
|
|
7
|
-
ruby '>2.6'
|
|
8
|
-
|
|
9
|
-
gem 'minitest', '5.18.0'
|
|
10
|
-
gem 'pidfile', '0.3.0'
|
|
11
|
-
gem 'rake', '13.0.6'
|
|
12
|
-
gem 'rubocop', '1.50.2'
|
|
13
|
-
gem 'terminal-table', '3.0.2'
|
|
14
|
-
gem 'video_transcoding', '0.25.3'
|
data/README.md
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Transcode
|
|
2
|
-
|
|
3
|
-
[](https://ci.appveyor.com/project/rdavid/transcode)
|
|
4
|
-
[](https://github.com/rdavid/transcode/actions/workflows/lint.yml)
|
|
5
|
-
[](https://github.com/rdavid/transcode/actions/workflows/ruby.yml)
|
|
6
|
-
[](https://badge.fury.io/rb/transcode)
|
|
7
|
-
[](https://codeclimate.com/github/rdavid/transcode/maintainability)
|
|
8
|
-
[](https://hitsofcode.com/view/github/rdavid/transcode)
|
|
9
|
-
[](https://github.com/rdavid/transcode/blob/master/LICENSE)
|
|
10
|
-
|
|
11
|
-
* [About](#about)
|
|
12
|
-
* [Installation](#installation)
|
|
13
|
-
* [Usage](#usage)
|
|
14
|
-
* [License](#license)
|
|
15
|
-
|
|
16
|
-
## About
|
|
17
|
-
|
|
18
|
-
`transcode` is a tool to transcode multiple video files. It enhances
|
|
19
|
-
[Don Melton](http://donmelton.com/)'s [Video
|
|
20
|
-
Transcoding](https://github.com/donmelton/video_transcoding/). It applies
|
|
21
|
-
Video Trascoding to each video file in a directory.
|
|
22
|
-
|
|
23
|
-
## Installation
|
|
24
|
-
|
|
25
|
-
The tool is designed to work on macOS, GNU/Linux, Windows, Unix-like OS. It is
|
|
26
|
-
packaged as a Gem and require Ruby version 2.6 or later. See “[Installing
|
|
27
|
-
Ruby](https://www.ruby-lang.org/en/documentation/installation/)” if you don't
|
|
28
|
-
have the proper version on your platform.
|
|
29
|
-
|
|
30
|
-
Use this command to install:
|
|
31
|
-
|
|
32
|
-
```sh
|
|
33
|
-
gem install transcode
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Updating
|
|
37
|
-
|
|
38
|
-
Use this command to update the package:
|
|
39
|
-
|
|
40
|
-
```sh
|
|
41
|
-
gem update transcode
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Requirements
|
|
45
|
-
|
|
46
|
-
See Video Transcoding's [requirements](https://github.com/donmelton/video_transcoding/blob/master/README.md?ts=2#requirements).
|
|
47
|
-
|
|
48
|
-
### Usage
|
|
49
|
-
|
|
50
|
-
```sh
|
|
51
|
-
transcode [options]
|
|
52
|
-
-a, --act Real encoding.
|
|
53
|
-
-s, --sca Scans files at the directory.
|
|
54
|
-
-m, --mp3 Converts files to mp3.
|
|
55
|
-
-d, --dir dir Directory to transcode.
|
|
56
|
-
-i, --tit tit Specific title by number.
|
|
57
|
-
-o, --out out Directory to output.
|
|
58
|
-
-u, --aud aud Audio stream numbers.
|
|
59
|
-
-t, --sub sub Subtitle stream numbers.
|
|
60
|
-
-w, --wid wid Width of the table.
|
|
61
|
-
-v, --version Shows version.
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Example
|
|
65
|
-
|
|
66
|
-
```sh
|
|
67
|
-
transcode -d <source> -o <destination> -u 1,3,1 -t 2,1,3
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
It converts three files from source with certain audio and subtitle streams.
|
|
71
|
-
Inspect first with `-s` option to see audio and subtitle streams.
|
|
72
|
-
|
|
73
|
-
## License
|
|
74
|
-
|
|
75
|
-
`transcode` is copyright [David Rabkin](http://cv.rabkin.co.il) and
|
|
76
|
-
available under a [Zero-Claus BSD license](https://github.com/rdavid/transcode/blob/master/LICENSE).
|
data/Rakefile
DELETED
data/appveyor.yml
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
version: '{build}'
|
|
3
|
-
skip_tags: true
|
|
4
|
-
clone_depth: 10
|
|
5
|
-
branches:
|
|
6
|
-
only:
|
|
7
|
-
- master
|
|
8
|
-
except:
|
|
9
|
-
- gh-pages
|
|
10
|
-
os: Windows Server 2012
|
|
11
|
-
environment:
|
|
12
|
-
matrix:
|
|
13
|
-
- ruby_version: "26-x64"
|
|
14
|
-
install:
|
|
15
|
-
- ps: |
|
|
16
|
-
$Env:PATH = "C:\Ruby${Env:ruby_version}\bin;${Env:PATH}"
|
|
17
|
-
- bundle config --local path vendor/bundle
|
|
18
|
-
- ruby -v
|
|
19
|
-
- bundle -v
|
|
20
|
-
build_script:
|
|
21
|
-
- bundle update
|
|
22
|
-
- bundle install
|
|
23
|
-
test_script:
|
|
24
|
-
- bundle exec rake --quiet
|
|
25
|
-
cache:
|
|
26
|
-
- vendor/bundle
|
data/transcode.gemspec
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/lib')
|
|
4
|
-
|
|
5
|
-
require 'transcode'
|
|
6
|
-
|
|
7
|
-
Gem::Specification.new do |s|
|
|
8
|
-
s.name = 'transcode'
|
|
9
|
-
s.version = Transcode::VERSION
|
|
10
|
-
s.date = Transcode::DATE
|
|
11
|
-
s.required_ruby_version = '>2.6'
|
|
12
|
-
s.summary = 'Tools to transcode batch of video files.'
|
|
13
|
-
s.description = <<-HERE
|
|
14
|
-
Transcode is a wraper on Video Transcoding.
|
|
15
|
-
HERE
|
|
16
|
-
s.license = '0BSD'
|
|
17
|
-
s.author = 'David Rabkin'
|
|
18
|
-
s.email = 'david@rabkin.co.il'
|
|
19
|
-
s.homepage = 'https://github.com/rdavid/transcode'
|
|
20
|
-
s.files = Dir['{bin,lib}/**/*'] + Dir['[A-Z]*'] + ['transcode.gemspec']
|
|
21
|
-
s.executables = ['transcode']
|
|
22
|
-
s.extra_rdoc_files = ['LICENSE', 'README.md']
|
|
23
|
-
s.require_paths = ['lib']
|
|
24
|
-
s.add_runtime_dependency 'pidfile', '0.3.0'
|
|
25
|
-
s.add_runtime_dependency 'terminal-table', '3.0.2'
|
|
26
|
-
s.add_runtime_dependency 'video_transcoding', '0.25.3'
|
|
27
|
-
s.add_development_dependency 'minitest', '5.18.0'
|
|
28
|
-
s.add_development_dependency 'rake', '13.0.6'
|
|
29
|
-
s.add_development_dependency 'rubocop', '1.50.2'
|
|
30
|
-
end
|