libis-format 0.9.38 → 0.9.39
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/.travis.yml +13 -13
- data/data/types.yml +85 -9
- data/lib/libis/format.rb +1 -0
- data/lib/libis/format/config.rb +2 -0
- data/lib/libis/format/converter/audio_converter.rb +181 -0
- data/lib/libis/format/converter/video_converter.rb +194 -0
- data/lib/libis/format/ffmpeg.rb +41 -0
- data/lib/libis/format/identifier.rb +1 -0
- data/lib/libis/format/pdf_to_pdfa.rb +1 -3
- data/lib/libis/format/pdfa_validator.rb +1 -1
- data/lib/libis/format/version.rb +1 -1
- data/libis-format.gemspec +1 -0
- data/spec/converter_spec.rb +116 -20
- data/spec/data/audio/carlin_disappointed.aac +0 -0
- data/spec/data/audio/carlin_disappointed.ac3 +0 -0
- data/spec/data/audio/carlin_disappointed.aiff +0 -0
- data/spec/data/audio/carlin_disappointed.au +0 -0
- data/spec/data/audio/carlin_disappointed.flac +0 -0
- data/spec/data/audio/carlin_disappointed.m4a +0 -0
- data/spec/data/audio/carlin_disappointed.mka +0 -0
- data/spec/data/audio/carlin_disappointed.mp3 +0 -0
- data/spec/data/audio/carlin_disappointed.ogg +0 -0
- data/spec/data/audio/carlin_disappointed.ra +0 -0
- data/spec/data/audio/carlin_disappointed.voc +0 -0
- data/spec/data/audio/carlin_disappointed.wav +0 -0
- data/spec/data/audio/carlin_disappointed.wma +0 -0
- data/spec/data/audio/greensleeves.aac +0 -0
- data/spec/data/audio/greensleeves.ac3 +0 -0
- data/spec/data/audio/greensleeves.aiff +0 -0
- data/spec/data/audio/greensleeves.au +0 -0
- data/spec/data/audio/greensleeves.flac +0 -0
- data/spec/data/audio/greensleeves.m4a +0 -0
- data/spec/data/audio/greensleeves.mka +0 -0
- data/spec/data/audio/greensleeves.mp3 +0 -0
- data/spec/data/audio/greensleeves.ogg +0 -0
- data/spec/data/audio/greensleeves.ra +0 -0
- data/spec/data/audio/greensleeves.voc +0 -0
- data/spec/data/audio/greensleeves.wav +0 -0
- data/spec/data/audio/greensleeves.wma +0 -0
- data/spec/data/audio/king_nonviolence.aac +0 -0
- data/spec/data/audio/king_nonviolence.ac3 +0 -0
- data/spec/data/audio/king_nonviolence.aiff +0 -0
- data/spec/data/audio/king_nonviolence.au +0 -0
- data/spec/data/audio/king_nonviolence.flac +0 -0
- data/spec/data/audio/king_nonviolence.m4a +0 -0
- data/spec/data/audio/king_nonviolence.mka +0 -0
- data/spec/data/audio/king_nonviolence.mp3 +0 -0
- data/spec/data/audio/king_nonviolence.ogg +0 -0
- data/spec/data/audio/king_nonviolence.ra +0 -0
- data/spec/data/audio/king_nonviolence.voc +0 -0
- data/spec/data/audio/king_nonviolence.wav +0 -0
- data/spec/data/audio/king_nonviolence.wma +0 -0
- data/spec/data/audio/top_gun_secret.aac +0 -0
- data/spec/data/audio/top_gun_secret.ac3 +0 -0
- data/spec/data/audio/top_gun_secret.aiff +0 -0
- data/spec/data/audio/top_gun_secret.au +0 -0
- data/spec/data/audio/top_gun_secret.flac +0 -0
- data/spec/data/audio/top_gun_secret.m4a +0 -0
- data/spec/data/audio/top_gun_secret.mka +0 -0
- data/spec/data/audio/top_gun_secret.mp3 +0 -0
- data/spec/data/audio/top_gun_secret.ogg +0 -0
- data/spec/data/audio/top_gun_secret.ra +0 -0
- data/spec/data/audio/top_gun_secret.voc +0 -0
- data/spec/data/audio/top_gun_secret.wav +0 -0
- data/spec/data/audio/top_gun_secret.wma +0 -0
- data/spec/data/video/SampleVideo_1080x720_2mb.flv +0 -0
- data/spec/data/video/SampleVideo_1080x720_2mb.mkv +0 -0
- data/spec/data/video/SampleVideo_1080x720_2mb.mp4 +0 -0
- data/spec/data/video/SampleVideo_176x144_2mb.3gp +0 -0
- data/spec/data/video/SampleVideo_320x240_2mb.3gp +0 -0
- data/spec/data/video/SampleVideo_360x240_2mb.flv +0 -0
- data/spec/data/video/SampleVideo_360x240_2mb.mkv +0 -0
- data/spec/data/video/SampleVideo_360x240_2mb.mp4 +0 -0
- data/spec/data/video/sample.avi +0 -0
- data/spec/data/video/sample.flv +0 -0
- data/spec/data/video/sample.mkv +0 -0
- data/spec/data/video/sample.mov +0 -0
- data/spec/data/video/sample.mp4 +0 -0
- data/spec/data/video/sample.mpg +0 -0
- data/spec/data/video/sample.swf +0 -0
- data/spec/data/video/sample.webm +0 -0
- data/spec/data/video/sample.wmv +0 -0
- data/spec/identifier_spec.rb +29 -39
- data/spec/spec_helper.rb +50 -1
- metadata +157 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d41852f4f00f61ffa6458f3ba0f9ce58215573d8
|
|
4
|
+
data.tar.gz: 96158848af69ff1ad5ffafc198d6f04b30a94f9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7db9b6c77b4429fa91ec099d8a10c55799050e6ca345b1af0f2273c5645841b2edb33b5be9cfe2967eedf52d0438e6bbe92e0ad499f2be3460ec8e53d7e076b1
|
|
7
|
+
data.tar.gz: 6399b4b84f80b7e48c2c85c3390e34fe39b70c8ea1c4a096dfd33981bbcc2eca2ba88f8be9e4738ff424f0e12446f5b898b1db248206ebd080fff098c585af6b
|
data/.travis.yml
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
sudo: false
|
|
3
|
+
dist: trusty
|
|
3
4
|
cache: bundler
|
|
4
5
|
rvm:
|
|
5
6
|
- 2.1.0
|
|
@@ -7,31 +8,25 @@ rvm:
|
|
|
7
8
|
- ruby-head
|
|
8
9
|
- jruby-9.0.1.0
|
|
9
10
|
jdk:
|
|
10
|
-
-
|
|
11
|
-
- oraclejdk7
|
|
11
|
+
- openjdk8
|
|
12
12
|
- oraclejdk8
|
|
13
13
|
matrix:
|
|
14
14
|
exclude:
|
|
15
|
-
- rvm: 2.1.0
|
|
16
|
-
jdk: oraclejdk7
|
|
17
15
|
- rvm: 2.1.0
|
|
18
16
|
jdk: oraclejdk8
|
|
19
|
-
- rvm: 2.2.0
|
|
20
|
-
jdk: oraclejdk7
|
|
21
17
|
- rvm: 2.2.0
|
|
22
18
|
jdk: oraclejdk8
|
|
23
|
-
- rvm: ruby-head
|
|
24
|
-
jdk: oraclejdk7
|
|
25
19
|
- rvm: ruby-head
|
|
26
20
|
jdk: oraclejdk8
|
|
27
|
-
allow_failures:
|
|
28
|
-
- rvm: 2.1.0
|
|
29
|
-
- rvm: 2.2.0
|
|
30
|
-
- rvm: ruby-head
|
|
31
|
-
- rvm: jruby-9.0.1.0
|
|
32
21
|
branches:
|
|
33
22
|
only:
|
|
34
23
|
- master
|
|
24
|
+
before_install:
|
|
25
|
+
- sudo add-apt-repository ppa:mc3man/trusty-media -y
|
|
26
|
+
- sudo apt-get update -y
|
|
27
|
+
- sudo apt-get install -y ffmpeg gstreamer0.10-ffmpeg
|
|
28
|
+
- sudo pip install opf-fido --upgrade --ignore-installed six
|
|
29
|
+
|
|
35
30
|
addons:
|
|
36
31
|
apt:
|
|
37
32
|
packages:
|
|
@@ -39,3 +34,8 @@ addons:
|
|
|
39
34
|
- imagemagick
|
|
40
35
|
- libreoffice
|
|
41
36
|
- ghostscript
|
|
37
|
+
- sox
|
|
38
|
+
- libsox-dev
|
|
39
|
+
- libsox-fmt-all
|
|
40
|
+
- libchromaprint-dev
|
|
41
|
+
- libchromaprint-tools
|
data/data/types.yml
CHANGED
|
@@ -70,66 +70,142 @@ IMAGE:
|
|
|
70
70
|
|
|
71
71
|
AUDIO:
|
|
72
72
|
|
|
73
|
-
WAV:
|
|
74
|
-
NAME: Waveform Audio File Format (WAVE)
|
|
75
|
-
MIME: audio/x-wav
|
|
76
|
-
EXTENSIONS: wav
|
|
77
|
-
|
|
78
73
|
MP3:
|
|
79
74
|
NAME: MPEG-1 or MPEG-2 Audio Layer III (MP3)
|
|
80
75
|
MIME: audio/mpeg
|
|
76
|
+
PUID: fmt/134
|
|
81
77
|
EXTENSIONS: mp3
|
|
82
78
|
|
|
83
79
|
FLAC:
|
|
84
80
|
NAME: Free Lossless Audio Codec (FLAC)
|
|
85
81
|
MIME: audio/flac
|
|
82
|
+
PUID: fmt/279
|
|
86
83
|
EXTENSIONS: flac
|
|
87
84
|
|
|
85
|
+
AC3:
|
|
86
|
+
NAME: Dolby Digital AC-3
|
|
87
|
+
MIME: audio/ac3
|
|
88
|
+
PUID: fmt/735
|
|
89
|
+
EXTENSIONS: ac3
|
|
90
|
+
|
|
91
|
+
AAC:
|
|
92
|
+
NAME: Advanced Audio Coding (AAC)
|
|
93
|
+
MIME: audio/aac
|
|
94
|
+
EXTENSIONS: aac
|
|
95
|
+
|
|
96
|
+
WMA:
|
|
97
|
+
NAME: Windows Media Audio (WMA)
|
|
98
|
+
MIME: audio/x-ms-wma
|
|
99
|
+
PUID: fmt/132
|
|
100
|
+
EXTENSIONS: wma
|
|
101
|
+
|
|
102
|
+
ALAC:
|
|
103
|
+
NAME: Apple Lossless Audio Codec (ALAC)
|
|
104
|
+
MIME: audio/alac
|
|
105
|
+
EXTENSIONS: alac
|
|
106
|
+
|
|
107
|
+
WAV:
|
|
108
|
+
NAME: Waveform Audio File Format (WAVE)
|
|
109
|
+
MIME: audio/x-wav
|
|
110
|
+
PUID: fmt/6, fmt/141, fmt/142, fmt/143, fmt/1, fmt/703, fmt/706, fmt/709, fmt/2, fmt/704, fmt/707, fmt/710, fmt/527, fmt/705, fmt/708, fmt/711, x-fmt/397, x-fmt/389, x-fmt/396, fmt/712, fmt/713
|
|
111
|
+
EXTENSIONS: wav
|
|
112
|
+
|
|
113
|
+
AIFF:
|
|
114
|
+
NAME: Audio Interchange File Format (AIFF)
|
|
115
|
+
MIME: audio/aiff
|
|
116
|
+
PUID: fmt/414, x-fmt/135, x-fmt/136
|
|
117
|
+
EXTENSIONS: aif aiff aifc
|
|
118
|
+
|
|
119
|
+
AMR:
|
|
120
|
+
NAME: Adaptive Multi-Rate Audio (AMR)
|
|
121
|
+
MIME: audio/amr
|
|
122
|
+
PUID: fmt/954
|
|
123
|
+
EXTENSIONS: amr
|
|
124
|
+
|
|
125
|
+
AU:
|
|
126
|
+
NAME: NeXT/Sun sound (AU)
|
|
127
|
+
MIME: audio/basic
|
|
128
|
+
PUID: x-fmt/139
|
|
129
|
+
EXTENSIONS: au
|
|
130
|
+
|
|
131
|
+
M4A:
|
|
132
|
+
NAME: MPEG-4 Media File (M4A)
|
|
133
|
+
MIME: audio/mp4
|
|
134
|
+
PUID: fmt/199, fmt/596
|
|
135
|
+
EXTENSIONS: m4a f4a
|
|
136
|
+
|
|
88
137
|
VIDEO:
|
|
89
138
|
|
|
90
|
-
|
|
139
|
+
MPG:
|
|
91
140
|
NAME: Moving Picture Experts Group (MPEG-1/MPEG-2)
|
|
92
141
|
MIME: video/mpeg
|
|
142
|
+
PUID: x-fmt/385 x-fmt/386 fmt/425 fmt/649 fmt/640
|
|
93
143
|
EXTENSIONS: mpg mpeg mp1 mp2 mp3 m1v m1a m2a mpa mpv
|
|
94
144
|
|
|
95
|
-
|
|
145
|
+
MP4:
|
|
96
146
|
NAME: Moving Picture Experts Group (MPEG-4)
|
|
97
|
-
MIME: video/mp4
|
|
98
|
-
|
|
147
|
+
MIME: video/mp4, application/mp4
|
|
148
|
+
PUID: fmt/199
|
|
149
|
+
EXTENSIONS: mp4,m4v,mpeg4
|
|
150
|
+
|
|
151
|
+
WEBM:
|
|
152
|
+
NAME: Webm
|
|
153
|
+
PUID: fmt/573
|
|
154
|
+
MIME: video/webm
|
|
155
|
+
EXTENSIONS: webm
|
|
156
|
+
|
|
157
|
+
FLASH:
|
|
158
|
+
NAME: Macromedia Flash
|
|
159
|
+
MIME: application/x-shockwave-flash
|
|
160
|
+
PUID: fmt/104 fmt/105 fmt/106 fmt/107 fmt/108 fmt/109 fmt/110
|
|
161
|
+
EXTENSIONS: swf
|
|
162
|
+
|
|
163
|
+
MKV:
|
|
164
|
+
NAME: Matroska Multimedia Container (MKV)
|
|
165
|
+
MIME: video/x-matroska
|
|
166
|
+
PUID: fmt/569
|
|
167
|
+
EXTENSIONS: mkv, mk3d, mka, mks
|
|
99
168
|
|
|
100
169
|
MJP2:
|
|
101
170
|
NAME: Motion JPEG 2000 (MJP2)
|
|
102
171
|
MIME: video/mj2
|
|
172
|
+
PUID: fmt/337
|
|
103
173
|
EXTENSIONS: mj2, mjp2
|
|
104
174
|
|
|
105
175
|
QTFF:
|
|
106
176
|
NAME: QuickTime File Format (QTFF)
|
|
107
177
|
MIME: video/quicktime
|
|
178
|
+
PUID: x-fmt/384
|
|
108
179
|
EXTENSIONS: mov, qt
|
|
109
180
|
|
|
110
181
|
AVI:
|
|
111
182
|
NAME: Audio Video Interleave (AVI)
|
|
112
183
|
MIME: video/x-msvideo
|
|
184
|
+
PUID: fmt/5
|
|
113
185
|
EXTENSIONS: avi
|
|
114
186
|
|
|
115
187
|
OGGV:
|
|
116
188
|
NAME: OGG Video (OGGV)
|
|
117
189
|
MIME: video/ogg
|
|
190
|
+
PUID: fmt/945
|
|
118
191
|
EXTENSIONS: ogv
|
|
119
192
|
|
|
120
193
|
WMV:
|
|
121
194
|
NAME: Windows Media Video (WMV)
|
|
122
195
|
MIME: video/x-ms-wmv
|
|
196
|
+
PUID: fmt/133 fmt/441
|
|
123
197
|
EXTENSIONS: wmv
|
|
124
198
|
|
|
125
199
|
DV:
|
|
126
200
|
NAME: Digital Video (DV)
|
|
127
201
|
MIME: video/dv
|
|
202
|
+
PUID: x-fmt/152
|
|
128
203
|
EXTENSIONS: dv
|
|
129
204
|
|
|
130
205
|
FLASH:
|
|
131
206
|
NAME: Flash video (FLV)
|
|
132
207
|
MIME: video/x-flv
|
|
208
|
+
PUID: x-fmt/382
|
|
133
209
|
EXTENSIONS: flv
|
|
134
210
|
|
|
135
211
|
TEXT:
|
data/lib/libis/format.rb
CHANGED
|
@@ -19,6 +19,7 @@ module Libis
|
|
|
19
19
|
autoload :PdfSplit, 'libis/format/pdf_split'
|
|
20
20
|
autoload :PdfToPdfa, 'libis/format/pdf_to_pdfa'
|
|
21
21
|
autoload :PdfaValidator, 'libis/format/pdfa_validator'
|
|
22
|
+
autoload :FFMpeg, 'libis/format/ffmpeg'
|
|
22
23
|
|
|
23
24
|
autoload :Converter, 'libis/format/converter'
|
|
24
25
|
|
data/lib/libis/format/config.rb
CHANGED
|
@@ -15,11 +15,13 @@ module Libis
|
|
|
15
15
|
Config[:ghostscript_path] = 'gs'
|
|
16
16
|
Config[:droid_path] = '/opt/droid/droid.sh'
|
|
17
17
|
Config[:fido_path] = '/usr/local/bin/fido'
|
|
18
|
+
Config[:ffmpeg_path] = 'ffmpeg'
|
|
18
19
|
data_dir = File.absolute_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'data'))
|
|
19
20
|
Config[:fido_formats] = [(File.join(data_dir, 'lias_formats.xml'))]
|
|
20
21
|
# noinspection RubyStringKeysInHashInspection
|
|
21
22
|
Config[:xml_validations] = [['archive/ead', File.join(data_dir, 'ead.xsd')]]
|
|
22
23
|
Config[:type_database] = File.join(data_dir, 'types.yml')
|
|
24
|
+
Config[:raw_audio_convert_cmd] = 'sox %s -e signed -b 16 -t wav %s rate %d channels %d'
|
|
23
25
|
|
|
24
26
|
end
|
|
25
27
|
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
require_relative 'base'
|
|
2
|
+
require 'libis/format/identifier'
|
|
3
|
+
require 'chromaprint'
|
|
4
|
+
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
module Libis
|
|
8
|
+
module Format
|
|
9
|
+
module Converter
|
|
10
|
+
|
|
11
|
+
class AudioConverter < Libis::Format::Converter::Base
|
|
12
|
+
|
|
13
|
+
def self.input_types
|
|
14
|
+
[:MP3, :FLAC, :AC3, :AAC, :WMA, :ALAC, :WAV, :AIFF, :AMR, :AU, :M4A]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.output_types(format = nil)
|
|
18
|
+
return [] unless input_types.include?(format)
|
|
19
|
+
[:MP3, :FLAC, :AC3, :AAC, :WMA, :ALAC, :WAV, :AIFF, :AMR, :AU, :M4A]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
super
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def quiet(v)
|
|
27
|
+
@flags[:quiet] = !!v
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def format(format)
|
|
31
|
+
@options[:format] = format
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def codec(codec)
|
|
35
|
+
@options[:codec] = codec
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def start(seconds)
|
|
39
|
+
@options[:start] = seconds.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def duration(seconds)
|
|
43
|
+
@options[:duration] = seconds.to_s
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def quality(value)
|
|
47
|
+
@options[:quality] = value.to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def bit_rate(value)
|
|
51
|
+
@options[:bit_rate] = value.to_s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def sampling_freq(value)
|
|
55
|
+
@options[:sampling_freq] = value.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def channels(value)
|
|
59
|
+
@options[:channels] = value.to_s
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def web_stream(value)
|
|
63
|
+
if value
|
|
64
|
+
@options[:codec] = 'mp3'
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def preset(stream, name)
|
|
69
|
+
(@options[:preset] ||= {})[stream] = name
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# def encoder(value)
|
|
73
|
+
# @options[:encoder] = value
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
76
|
+
# def encoder_options(value)
|
|
77
|
+
# @options[:encoder_options] = value
|
|
78
|
+
# end
|
|
79
|
+
|
|
80
|
+
def convert(source, target, _format, opts = {})
|
|
81
|
+
super
|
|
82
|
+
|
|
83
|
+
FileUtils.mkpath(File.dirname(target))
|
|
84
|
+
|
|
85
|
+
if source.is_a? Array
|
|
86
|
+
|
|
87
|
+
assemble_and_convert(source, target)
|
|
88
|
+
|
|
89
|
+
elsif File.directory?(source)
|
|
90
|
+
|
|
91
|
+
sources = Dir[File.join(source, '**', '*')].reject {|p| File.directory? p}
|
|
92
|
+
assemble_and_convert(sources, target)
|
|
93
|
+
|
|
94
|
+
else
|
|
95
|
+
|
|
96
|
+
convert_file(source, target)
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
target
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def assemble_and_convert(sources, target)
|
|
105
|
+
Tempfile.create(%w(list .txt)) do |f|
|
|
106
|
+
sources.each {|src| f.puts src}
|
|
107
|
+
opts[:global] ||= []
|
|
108
|
+
opts[:global] += %w(-f concat)
|
|
109
|
+
f.close
|
|
110
|
+
target = convert_file(f.to_path, target)
|
|
111
|
+
end
|
|
112
|
+
target
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def sounds_like(file1, file2, threshold, rate, channels)
|
|
116
|
+
rate ||= 96000
|
|
117
|
+
channels ||= 2
|
|
118
|
+
threshold ||= 0.85
|
|
119
|
+
|
|
120
|
+
if File.exists?(file1) && File.exists?(file2)
|
|
121
|
+
# Convert input files into raw 16-bit signed audio (WAV) to process with Chramaprint
|
|
122
|
+
file1_raw = File.join('', 'tmp', File.basename(file1) + '.wav')
|
|
123
|
+
file2_raw = File.join('', 'tmp', File.basename(file2) + '.wav')
|
|
124
|
+
FileUtils.rm(file1_raw, force: true)
|
|
125
|
+
FileUtils.rm(file2_raw, force: true)
|
|
126
|
+
cvt_cmd = Libis::Format::Config[:raw_audio_convert_cmd]
|
|
127
|
+
%x"#{cvt_cmd % [file1, file1_raw, rate, channels]}"
|
|
128
|
+
%x"#{cvt_cmd % [file2, file2_raw, rate, channels]}"
|
|
129
|
+
file1_audio = File.binread(file1_raw)
|
|
130
|
+
file2_audio = File.binread(file2_raw)
|
|
131
|
+
|
|
132
|
+
# Get audio fingerprints
|
|
133
|
+
chromaprint = Chromaprint::Context.new(rate, channels, Chromaprint::ALGORITHM_TEST3)
|
|
134
|
+
file1_fp = chromaprint.get_fingerprint(file1_audio)
|
|
135
|
+
file2_fp = chromaprint.get_fingerprint(file2_audio)
|
|
136
|
+
|
|
137
|
+
# Cleanup files
|
|
138
|
+
FileUtils.rm(file1_raw, force: true)
|
|
139
|
+
FileUtils.rm(file2_raw, force: true)
|
|
140
|
+
|
|
141
|
+
# Compare fingerprints and compare result against threshold
|
|
142
|
+
cmp = file1_fp.compare(file2_fp)
|
|
143
|
+
# puts "Threshold[#{File.basename(exp_file)},#{File.basename(tgt_file)}: #{cmp}"
|
|
144
|
+
cmp > threshold
|
|
145
|
+
else
|
|
146
|
+
false
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
rescue Exception => e
|
|
150
|
+
error "Error comparing sound file #{file1} and #{file2}: #{e.message} @ #{e.backtrace.first}"
|
|
151
|
+
false
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
protected
|
|
155
|
+
|
|
156
|
+
def convert_file(source, target)
|
|
157
|
+
opts = {global: [], input: [], filter: [], output: []}
|
|
158
|
+
opts[:global] << '-hide_banner'
|
|
159
|
+
opts[:global] << '-loglevel' << (@options[:quiet] ? 'fatal' : 'warning')
|
|
160
|
+
opts[:output] << '-vn' # disable input video stream in case it exists
|
|
161
|
+
opts[:output] << '-codec:a' << @options[:codec] if @options[:codec]
|
|
162
|
+
opts[:output] << '-map_metadata:g' << '0:g' # Copy global metadata
|
|
163
|
+
opts[:output] << '-map_metadata:s:a' << '0:s:a' # Copy audio metadata
|
|
164
|
+
opts[:input] << '-accurate_seek' << (@options[:start].to_i < 0 ? '-sseof' : '-ss') << @options[:start] if @options[:start]
|
|
165
|
+
opts[:input] << '-t' << @options[:duration] if @options[:duration]
|
|
166
|
+
opts[:output] << '-q:a' << @options[:quality] if @options[:quality]
|
|
167
|
+
opts[:output] << '-b:a' << @options[:bit_rate] if @options[:bit_rate]
|
|
168
|
+
opts[:output] << '-ar' << @options[:sampling_freq] if @options[:sampling_freq]
|
|
169
|
+
opts[:output] << '-ac' << @options[:channels] if @options[:channels]
|
|
170
|
+
opts[:output] << '-f' << @options[:format] if @options[:format]
|
|
171
|
+
result = Libis::Format::FFMpeg.run(source, target, opts)
|
|
172
|
+
info "FFMpeg output: #{result}"
|
|
173
|
+
result
|
|
174
|
+
target
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require_relative 'base'
|
|
2
|
+
require 'libis/format/ffmpeg'
|
|
3
|
+
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
6
|
+
module Libis
|
|
7
|
+
module Format
|
|
8
|
+
module Converter
|
|
9
|
+
|
|
10
|
+
class VideoConverter < Libis::Format::Converter::Base
|
|
11
|
+
|
|
12
|
+
def self.input_types
|
|
13
|
+
[:WEBM, :M4V, :MPEG, :MJP2, :QTFF, :AVI, :OGGV, :WMV, :DV, :FLASH]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.output_types(format = nil)
|
|
17
|
+
return [] unless input_types.include?(format)
|
|
18
|
+
[:GIF, :AVI, :FLV, :MKV, :MOV, :MP4, :MPG, :OGGV, :SWF, :WEBM, :WMV]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def quiet(v)
|
|
26
|
+
@flags[:quiet] = !!v
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def format(format)
|
|
30
|
+
@options[:format] = format
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def audio_channels(value)
|
|
34
|
+
@options[:audio_channels] = value.to_s
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def audio_codec(codec)
|
|
38
|
+
@options[:audio_codec] = codec
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def video_codec(codec)
|
|
42
|
+
@options[:video_codec] = codec
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def start(seconds)
|
|
46
|
+
@options[:start] = seconds.to_s
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def duration(seconds)
|
|
50
|
+
@options[:duration] = seconds.to_s
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def audio_quality(value)
|
|
54
|
+
@options[:audio_quality] = value.to_s
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def video_quality(value)
|
|
58
|
+
@options[:video_quality] = value.to_s
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def audio_bitrate(value)
|
|
62
|
+
@options[:audio_bitrate] = value.to_s
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def video_bitrate(value)
|
|
66
|
+
@options[:video_bitrate] = value.to_s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def constant_rate_factor(value)
|
|
70
|
+
@options[:crf] = value.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def frame_rate(value)
|
|
74
|
+
@options[:frame_rate] = value.to_s
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def sampling_freq(value)
|
|
78
|
+
@options[:sampling_freq] = value.to_s
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def scale(width_x_height)
|
|
82
|
+
@options[:scale] = width_x_height
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def web_stream(value)
|
|
86
|
+
if value
|
|
87
|
+
@options[:video_codec] = 'h264'
|
|
88
|
+
@options[:audio_codec] = 'acc'
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def preset(name)
|
|
93
|
+
@options[:preset] = name
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def audio_preset(name)
|
|
97
|
+
@options[:audio_preset] = name
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def video_preset(name)
|
|
101
|
+
@options[:video_preset] = name
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# def video_encoder(value)
|
|
105
|
+
# @options[:video_encoder] = value
|
|
106
|
+
# end
|
|
107
|
+
#
|
|
108
|
+
# def audio_encoder(value)
|
|
109
|
+
# @options[:audio_encoder] = value
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
# def encoder_options(value)
|
|
113
|
+
# @options[:encoder_options] = value
|
|
114
|
+
# end
|
|
115
|
+
|
|
116
|
+
def convert(source, target, _format, opts = {})
|
|
117
|
+
super
|
|
118
|
+
|
|
119
|
+
FileUtils.mkpath(File.dirname(target))
|
|
120
|
+
|
|
121
|
+
if source.is_a? Array
|
|
122
|
+
|
|
123
|
+
assemble_and_convert(source, target)
|
|
124
|
+
|
|
125
|
+
elsif File.directory?(source)
|
|
126
|
+
|
|
127
|
+
sources = Dir[File.join(source, '**', '*')].reject {|p| File.directory? p}
|
|
128
|
+
assemble_and_convert(sources, target)
|
|
129
|
+
|
|
130
|
+
else
|
|
131
|
+
|
|
132
|
+
convert_file(source, target)
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
target
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def assemble_and_convert(sources, target)
|
|
141
|
+
Tempfile.create(%w(list .txt)) do |f|
|
|
142
|
+
sources.each {|src| f.puts src}
|
|
143
|
+
opts[:global] ||= []
|
|
144
|
+
opts[:global] += %w(-f concat)
|
|
145
|
+
f.close
|
|
146
|
+
target = convert_file(f.to_path, target)
|
|
147
|
+
end
|
|
148
|
+
target
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
protected
|
|
152
|
+
|
|
153
|
+
def convert_file(source, target)
|
|
154
|
+
# FLV special: only supports aac and speex audio codecs
|
|
155
|
+
format = (@options[:format] || File.extname(target)[1..-1]).to_s.downcase
|
|
156
|
+
@options[:audio_codec] ||= 'aac' if %w'flv'.include?(format)
|
|
157
|
+
|
|
158
|
+
# FLV special: only supports aac and speex audio codecs
|
|
159
|
+
format = (@options[:format] || File.extname(target)[1..-1]).to_s.downcase
|
|
160
|
+
@options[:audio_codec] ||= 'mp3' if %w'swf'.include?(format)
|
|
161
|
+
|
|
162
|
+
# Set up FFMpeg command line parameters
|
|
163
|
+
opts = {global: [], input: [], filter: [], output: []}
|
|
164
|
+
opts[:global] << '-hide_banner'
|
|
165
|
+
opts[:global] << '-loglevel' << (@options[:quiet] ? 'fatal' : 'warning')
|
|
166
|
+
opts[:output] << '-ac' << @options[:audio_channels] if @options[:audio_channels]
|
|
167
|
+
opts[:output] << '-c:a' << @options[:audio_codec] if @options[:audio_codec]
|
|
168
|
+
opts[:output] << '-c:v' << @options[:video_codec] if @options[:video_codec]
|
|
169
|
+
opts[:output] << '-b:a' << @options[:audio_bitrate] if @options[:audio_bitrate]
|
|
170
|
+
opts[:output] << '-b:v' << @options[:video_bitrate] if @options[:video_bitrate]
|
|
171
|
+
opts[:output] << '-crf' << @options[:crf] if @options[:crf]
|
|
172
|
+
opts[:output] << '-map_metadata:g' << '0:g' # Copy global metadata
|
|
173
|
+
opts[:output] << '-map_metadata:s:a' << '0:s:a' # Copy audio metadata
|
|
174
|
+
opts[:output] << '-map_metadata:s:v' << '0:s:v' # Copy video metadata
|
|
175
|
+
opts[:input] << '-accurate_seek' << (@options[:start].to_i < 0 ? '-sseof' : '-ss') << @options[:start] if @options[:start]
|
|
176
|
+
opts[:input] << '-t' << @options[:duration] if @options[:duration]
|
|
177
|
+
opts[:output] << '-qscale' << @options[:video_quality] if @options[:video_quality]
|
|
178
|
+
opts[:output] << '-q:a' << @options[:audio_quality] if @options[:audio_quality]
|
|
179
|
+
opts[:output] << '-r' << @options[:frame_rate] if @options[:frame_rate]
|
|
180
|
+
opts[:output] << '-ar' << @options[:sampling_freq] if @options[:sampling_freq]
|
|
181
|
+
opts[:output] << '-f' << @options[:format] if @options[:format]
|
|
182
|
+
opts[:output] << '-pre' << @options[:preset] if @options[:preset]
|
|
183
|
+
opts[:output] << '-apre' << @options[:audio_preset] if @options[:audio_preset]
|
|
184
|
+
opts[:output] << '-vpre' << @options[:video_preset] if @options[:video_preset]
|
|
185
|
+
result = Libis::Format::FFMpeg.run(source, target, opts)
|
|
186
|
+
info "FFMpeg output: #{result}"
|
|
187
|
+
target
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|