format_parser 0.24.0 → 0.24.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/lib/format_parser/version.rb +1 -1
- data/lib/parsers/mp3_parser.rb +14 -8
- data/spec/parsers/mp3_parser_spec.rb +14 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c76879d955fbe7598ee7ccdfc663876a29621e1fe4e54721edbba19d8e5f9c81
|
4
|
+
data.tar.gz: 7cd4161abb24e1a195fec86dc6c9ced63cb642832edf4d4d9c33129208fdf8b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6125db42f078e6e7d4fb0a9111ce29d6750a6b5fedcbfd9a7b28f66fca8fbf59e513f2b91cccc7a2409744dd1a49b7e60361bc7af0c8414bde42e9fd535941e9
|
7
|
+
data.tar.gz: f285a67739a9722a77aa9871e0d9b553a463dd22090c3728c8f97898740b303d91c214f2565d679895325e2d45399be311550e4263554d5e056d2ce528108374
|
data/CHANGELOG.md
CHANGED
data/lib/parsers/mp3_parser.rb
CHANGED
@@ -20,13 +20,14 @@ class FormatParser::MP3Parser
|
|
20
20
|
|
21
21
|
# We limit the number of MPEG frames we scan
|
22
22
|
# to obtain our duration estimation
|
23
|
-
MAX_FRAMES_TO_SCAN =
|
23
|
+
MAX_FRAMES_TO_SCAN = 500
|
24
24
|
|
25
25
|
# Default frame size for mp3
|
26
26
|
SAMPLES_PER_FRAME = 1152
|
27
27
|
|
28
28
|
# For some edge cases
|
29
29
|
ZIP_LOCAL_ENTRY_SIGNATURE = "PK\x03\x04\x14\x00".b
|
30
|
+
PNG_HEADER_BYTES = [137, 80, 78, 71, 13, 10, 26, 10].pack('C*')
|
30
31
|
|
31
32
|
# Wraps the Tag object returned by ID3Tag in such
|
32
33
|
# a way that a usable JSON representation gets
|
@@ -60,8 +61,12 @@ class FormatParser::MP3Parser
|
|
60
61
|
# To avoid having that happen, we check for the PKZIP signature -
|
61
62
|
# local entry header signature - at the very start of the file.
|
62
63
|
# If the file is too small safe_read will fail too and the parser
|
63
|
-
# will terminate here.
|
64
|
-
|
64
|
+
# will terminate here. Same with PNGs. In the future
|
65
|
+
# we should implement "confidence" for MP3 as of all our formats
|
66
|
+
# it is by far the most lax.
|
67
|
+
header = safe_read(io, 8)
|
68
|
+
return if header.start_with?(ZIP_LOCAL_ENTRY_SIGNATURE)
|
69
|
+
return if header.start_with?(PNG_HEADER_BYTES)
|
65
70
|
|
66
71
|
# Read all the ID3 tags (or at least attempt to)
|
67
72
|
io.seek(0)
|
@@ -131,27 +136,28 @@ class FormatParser::MP3Parser
|
|
131
136
|
# if you have a minute. https://pypi.python.org/pypi/tinytag
|
132
137
|
def parse_mpeg_frames(io)
|
133
138
|
mpeg_frames = []
|
139
|
+
bytes_to_read = 4
|
134
140
|
|
135
141
|
MAX_FRAMES_TO_SCAN.times do |frame_i|
|
136
142
|
# Read through until we can latch onto the 11 sync bits. Read in 4-byte
|
137
143
|
# increments to save on read() calls
|
138
|
-
data = io.read(
|
144
|
+
data = io.read(bytes_to_read)
|
139
145
|
|
140
146
|
# If we are at EOF - stop iterating
|
141
|
-
break unless data && data.bytesize ==
|
147
|
+
break unless data && data.bytesize == bytes_to_read
|
142
148
|
|
143
149
|
# Look for the sync pattern. It can be either the last byte being 0xFF,
|
144
150
|
# or any of the 2 bytes in sequence being 0xFF and > 0xF0.
|
145
151
|
four_bytes = data.unpack('C4')
|
146
152
|
seek_jmp = sync_bytes_offset_in_4_byte_seq(four_bytes)
|
147
153
|
if seek_jmp > 0
|
148
|
-
io.seek(io.pos + seek_jmp)
|
154
|
+
io.seek(io.pos - bytes_to_read + seek_jmp)
|
149
155
|
next
|
150
156
|
end
|
151
157
|
|
152
158
|
# Once we are past that stage we have latched onto a sync frame header
|
153
159
|
sync, conf, bitrate_freq, rest = four_bytes
|
154
|
-
frame_detail = parse_mpeg_frame_header(io.pos -
|
160
|
+
frame_detail = parse_mpeg_frame_header(io.pos - bytes_to_read, sync, conf, bitrate_freq, rest)
|
155
161
|
mpeg_frames << frame_detail
|
156
162
|
|
157
163
|
# There might be a xing header in the first frame that contains
|
@@ -166,7 +172,7 @@ class FormatParser::MP3Parser
|
|
166
172
|
end
|
167
173
|
end
|
168
174
|
if frame_detail.frame_length > 1 # jump over current frame body
|
169
|
-
io.seek(io.pos + frame_detail.frame_length -
|
175
|
+
io.seek(io.pos + frame_detail.frame_length - bytes_to_read)
|
170
176
|
end
|
171
177
|
end
|
172
178
|
[nil, mpeg_frames]
|
@@ -15,6 +15,12 @@ describe FormatParser::MP3Parser do
|
|
15
15
|
expect(parsed.media_duration_seconds).to be_within(0.1).of(0.836)
|
16
16
|
end
|
17
17
|
|
18
|
+
it 'does not misdetect a PNG' do
|
19
|
+
fpath = fixtures_dir + '/PNG/anim.png'
|
20
|
+
parsed = subject.call(File.open(fpath, 'rb'))
|
21
|
+
expect(parsed).to be_nil
|
22
|
+
end
|
23
|
+
|
18
24
|
describe 'title/artist/album attributes' do
|
19
25
|
let(:parsed) { subject.call(File.open(fpath, 'rb')) }
|
20
26
|
|
@@ -90,6 +96,14 @@ describe FormatParser::MP3Parser do
|
|
90
96
|
expect(parsed.title).to eq('test')
|
91
97
|
end
|
92
98
|
|
99
|
+
it 'reads the mpeg frames correctly' do
|
100
|
+
fpath = fixtures_dir + '/MP3/test_read_frames.mp3'
|
101
|
+
|
102
|
+
parsed = subject.call(File.open(fpath, 'rb'))
|
103
|
+
|
104
|
+
expect(parsed.audio_sample_rate_hz). to eq(48000)
|
105
|
+
end
|
106
|
+
|
93
107
|
it 'parses the Cassy MP3' do
|
94
108
|
fpath = fixtures_dir + '/MP3/Cassy.mp3'
|
95
109
|
parsed = subject.call(File.open(fpath, 'rb'))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: format_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.24.
|
4
|
+
version: 0.24.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Berman
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-09-
|
12
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ks
|
@@ -292,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
292
292
|
- !ruby/object:Gem::Version
|
293
293
|
version: '0'
|
294
294
|
requirements: []
|
295
|
-
rubygems_version: 3.0.
|
295
|
+
rubygems_version: 3.0.3
|
296
296
|
signing_key:
|
297
297
|
specification_version: 4
|
298
298
|
summary: A library for efficient parsing of file metadata
|