From a183a14322bcdfc31937abbab3d99ceeb0ff72a6 Mon Sep 17 00:00:00 2001 From: Borewit Date: Sun, 28 Apr 2019 18:22:50 +0200 Subject: [PATCH 1/4] Skip unit test using /dev/null on Windows platforms. --- test.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test.js b/test.js index 0c5069b4..fb99e214 100644 --- a/test.js +++ b/test.js @@ -257,13 +257,15 @@ for (const type of types) { } } -test('.stream() method - empty stream', async t => { - const emptyStream = fs.createReadStream('/dev/null'); - await t.throwsAsync( - fileType.stream(emptyStream), - /Expected the `input` argument to be of type `Uint8Array` / - ); -}); +if (process.platform !== 'win32') { + test('.stream() method - empty stream', async t => { + const emptyStream = fs.createReadStream('/dev/null'); + await t.throwsAsync( + fileType.stream(emptyStream), + /Expected the `input` argument to be of type `Uint8Array` / + ); + }); +} test('fileType.minimumBytes', t => { t.true(fileType.minimumBytes > 4000); From 39502494d6208fa8dd23cdd1cdd7b489b26a33fa Mon Sep 17 00:00:00 2001 From: Borewit Date: Sun, 28 Apr 2019 19:28:59 +0200 Subject: [PATCH 2/4] Add/update support for MPEG-4/ADTS/AAC; mapped to aac extension. Related #206 --- fixture/fixture-adts-2.aac | Bin 0 -> 5201 bytes .../{fixture-aac-adts.mp4 => fixture-adts.aac} | Bin index.d.ts | 3 ++- index.js | 2 +- readme.md | 1 + test.js | 11 ++++++++--- 6 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 fixture/fixture-adts-2.aac rename fixture/{fixture-aac-adts.mp4 => fixture-adts.aac} (100%) diff --git a/fixture/fixture-adts-2.aac b/fixture/fixture-adts-2.aac new file mode 100644 index 0000000000000000000000000000000000000000..06036ca07dfb1ae862d3d4fb805dc6f463671053 GIT binary patch literal 5201 zcmezWF`z-O{*NL9E5icm{|6XG0XziE7dOD!RAf~D2L<{3KZ*jQL5?1*=1b5;sKYM@ zhdD5rkA^u$fYK { check([0xFF, 0xF0], {offset: start, mask: [0xFF, 0xFC]}) // MPEG 4 layer 0 using ADTS ) { return { - ext: 'mp4', + ext: 'aac', mime: 'audio/mpeg' }; } diff --git a/readme.md b/readme.md index f6859d82..6b1e42d5 100644 --- a/readme.md +++ b/readme.md @@ -221,6 +221,7 @@ Type: [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream - [`alias`](https://en.wikipedia.org/wiki/Alias_%28Mac_OS%29) - macOS Alias file - [`voc`](https://wiki.multimedia.cx/index.php/Creative_Voice) - Creative Voice File - [`ac3`](https://www.atsc.org/standard/a522012-digital-audio-compression-ac-3-e-ac-3-standard-12172012/) - ATSC A/52 Audio File +- [`aac`](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) - Advanced Audio Coding *SVG isn't included as it requires the whole file to be read, but you can get it [here](https://github.com/sindresorhus/is-svg).* diff --git a/test.js b/test.js index fb99e214..da7c4a32 100644 --- a/test.js +++ b/test.js @@ -108,7 +108,9 @@ const types = [ 'lnk', 'alias', 'voc', - 'ac3' + 'ac3', + 'pcap', + 'aac' ]; // Define an entry here only if the fixture has a different @@ -153,8 +155,7 @@ const names = { 'fixture-isomv2', 'fixture-mp4v2', 'fixture-m4v', - 'fixture-dash', - 'fixture-aac-adts' + 'fixture-dash' ], tif: [ 'fixture-big-endian', @@ -199,6 +200,10 @@ const names = { tar: [ 'fixture', 'fixture-v7' + ], + aac: [ + 'fixture-adts', + 'fixture-adts-2' ] }; From 2b4af5167c50beb55727dd351262871c4bf2281f Mon Sep 17 00:00:00 2001 From: Borewit Date: Tue, 30 Apr 2019 18:07:43 +0200 Subject: [PATCH 3/4] #208 Fix MPEG/ADTS test, ADTS to audio/aac mime-type, skip ID3 tag-headers. --- index.js | 100 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/index.js b/index.js index cd317a8c..73c4b952 100644 --- a/index.js +++ b/index.js @@ -38,6 +38,17 @@ const fileType = input => { const checkString = (header, options) => check(stringToBytes(header), options); + /** + * Specialized function to read ID3 payload length + * @param buf Buffer + * @param off offset in buffer + * @returns {number} ID3 payload length + */ + function readUINT32SYNCSAFE(buf, off) { + return (buf[off + 3] & 0x7F) | ((buf[off + 2]) << 7) | + ((buf[off + 1]) << 14) | ((buf[off]) << 21); + } + if (check([0xFF, 0xD8, 0xFF])) { return { ext: 'jpg', @@ -409,46 +420,71 @@ const fileType = input => { }; } - // Check for MPEG header at different starting offsets + let flagId3 = false; + for (let start = 0; start < 2 && start < (buffer.length - 16); start++) { - if ( - check([0x49, 0x44, 0x33], {offset: start}) || // ID3 header - check([0xFF, 0xE2], {offset: start, mask: [0xFF, 0xE6]}) // MPEG 1 or 2 Layer 3 header - ) { - return { - ext: 'mp3', - mime: 'audio/mpeg' - }; + // Check for ID3 header + if (buffer.length >= start + 10 && checkString('ID3', {offset: start})) { + const id3Len = readUINT32SYNCSAFE(buffer, start + 6); + start += (10 + id3Len - 1); // Skip ID3 header + flagId3 = true; + continue; } - if ( - check([0xFF, 0xE4], {offset: start, mask: [0xFF, 0xE6]}) // MPEG 1 or 2 Layer 2 header - ) { - return { - ext: 'mp2', - mime: 'audio/mpeg' - }; - } + // Check MPEG 1 or 2 Layer 3 header, or 'layer 0' for ADTS (MPEG sync-word 0xFFE) + if (buffer.length >= start + 2 && check([0xFF, 0xE0], {offset: start, mask: [0xFF, 0xE0]})) { + // Check for ADTS header (last bit of sync-word 0xFFF & layer=0) + if (check([0x10], {offset: start + 1, mask: [0x16]})) { + // Check for (ADTS) MPEG-2 + if (check([0x08], {offset: start + 1, mask: [0x08]})) { + return { + ext: 'mp2', + mime: 'audio/mpeg' + }; + } - if ( - check([0xFF, 0xF8], {offset: start, mask: [0xFF, 0xFC]}) // MPEG 2 layer 0 using ADTS - ) { - return { - ext: 'mp2', - mime: 'audio/mpeg' - }; - } + // Must be (ADTS) MPEG-4 + return { + ext: 'aac', + mime: 'audio/aac' + }; + } - if ( - check([0xFF, 0xF0], {offset: start, mask: [0xFF, 0xFC]}) // MPEG 4 layer 0 using ADTS - ) { - return { - ext: 'aac', - mime: 'audio/mpeg' - }; + // MPEG 1 or 2 Layer 3 header + // Check for MPEG layer 3 + if (check([0x02], {offset: start + 1, mask: [0x06]})) { + return { + ext: 'mp3', + mime: 'audio/mpeg' + }; + } + + // Check for MPEG layer 2 + if (check([0x04], {offset: start + 1, mask: [0x06]})) { + return { + ext: 'mp2', + mime: 'audio/mpeg' + }; + } + + // Check for MPEG layer 1 + if (check([0x06], {offset: start + 1, mask: [0x06]})) { + return { + ext: 'mp1', + mime: 'audio/mpeg' + }; + } } } + if (flagId3) { + // Guess it is MP3 if only an ID3 tag header is found + return { + ext: 'mp3', + mime: 'audio/mpeg' + }; + } + if ( check([0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41], {offset: 4}) ) { From 16fa1cbdfb4378ae702981372d38e32c64585e61 Mon Sep 17 00:00:00 2001 From: Borewit Date: Tue, 30 Apr 2019 18:16:09 +0200 Subject: [PATCH 4/4] #208, #136 Mapped ADTS/MPEG-2/ACC to ext=.acc, mime=audio/aac. --- ...fixture-faac-adts.mp2 => fixture-adts-mpeg2.aac} | Bin ...{fixture-adts-2.aac => fixture-adts-mpeg4-2.aac} | Bin .../{fixture-adts.aac => fixture-adts-mpeg4.aac} | Bin index.js | 4 ++-- test.js | 8 ++++---- 5 files changed, 6 insertions(+), 6 deletions(-) rename fixture/{fixture-faac-adts.mp2 => fixture-adts-mpeg2.aac} (100%) rename fixture/{fixture-adts-2.aac => fixture-adts-mpeg4-2.aac} (100%) rename fixture/{fixture-adts.aac => fixture-adts-mpeg4.aac} (100%) diff --git a/fixture/fixture-faac-adts.mp2 b/fixture/fixture-adts-mpeg2.aac similarity index 100% rename from fixture/fixture-faac-adts.mp2 rename to fixture/fixture-adts-mpeg2.aac diff --git a/fixture/fixture-adts-2.aac b/fixture/fixture-adts-mpeg4-2.aac similarity index 100% rename from fixture/fixture-adts-2.aac rename to fixture/fixture-adts-mpeg4-2.aac diff --git a/fixture/fixture-adts.aac b/fixture/fixture-adts-mpeg4.aac similarity index 100% rename from fixture/fixture-adts.aac rename to fixture/fixture-adts-mpeg4.aac diff --git a/index.js b/index.js index 73c4b952..86120637 100644 --- a/index.js +++ b/index.js @@ -438,8 +438,8 @@ const fileType = input => { // Check for (ADTS) MPEG-2 if (check([0x08], {offset: start + 1, mask: [0x08]})) { return { - ext: 'mp2', - mime: 'audio/mpeg' + ext: 'aac', + mime: 'audio/aac' }; } diff --git a/test.js b/test.js index da7c4a32..7280dc33 100644 --- a/test.js +++ b/test.js @@ -139,8 +139,7 @@ const names = { ], mp2: [ 'fixture', - 'fixture-mpa', - 'fixture-faac-adts' + 'fixture-mpa' ], mp3: [ 'fixture', @@ -202,8 +201,9 @@ const names = { 'fixture-v7' ], aac: [ - 'fixture-adts', - 'fixture-adts-2' + 'fixture-adts-mpeg4', + 'fixture-adts-mpeg4-2', + 'fixture-adts-mpeg2' ] };