├── .eslintrc.js
├── .gitignore
├── .idea
├── inspectionProfiles
│ └── Project_Default.xml
└── runConfigurations
│ └── Tests__Unit.xml
├── .mocharc.json
├── .npmignore
├── .nycrc
├── LICENSE
├── README.md
├── appveyor.yml
├── docs
├── .nojekyll
├── README.md
├── classes
│ ├── AacFile.md
│ ├── AacFileSettings.md
│ ├── AiffFile.md
│ ├── ApeFile.md
│ ├── ApeFileSettings.md
│ ├── ApeTag.md
│ ├── ApeTagItem.md
│ ├── AsfBaseObject.md
│ ├── AsfContentDescriptionObject.md
│ ├── AsfContentDescriptor.md
│ ├── AsfExtendedContentDescriptionObject.md
│ ├── AsfFile.md
│ ├── AsfFilePropertiesObject.md
│ ├── AsfHeaderExtensionObject.md
│ ├── AsfHeaderObject.md
│ ├── AsfMetadataDescriptor.md
│ ├── AsfMetadataLibraryObject.md
│ ├── AsfPaddingObject.md
│ ├── AsfStreamPropertiesObject.md
│ ├── AsfTag.md
│ ├── AsfUnknownObject.md
│ ├── AviFileSettings.md
│ ├── AviStream.md
│ ├── ByteVector.md
│ ├── CombinedTag.md
│ ├── CorruptFileError.md
│ ├── DivxTag.md
│ ├── EndTag.md
│ ├── File.md
│ ├── FlacBlock.md
│ ├── FlacFile.md
│ ├── FlacFileSettings.md
│ ├── FlacTag.md
│ ├── Genres.md
│ ├── Id3v1Tag.md
│ ├── Id3v2AttachmentFrame.md
│ ├── Id3v2CommentsFrame.md
│ ├── Id3v2EventTimeCode.md
│ ├── Id3v2EventTimeCodeFrame.md
│ ├── Id3v2ExtendedHeader.md
│ ├── Id3v2Frame.md
│ ├── Id3v2FrameFactory.md
│ ├── Id3v2FrameHeader.md
│ ├── Id3v2FrameIdentifier.md
│ ├── Id3v2MusicCdIdentifierFrame.md
│ ├── Id3v2PlayCountFrame.md
│ ├── Id3v2PopularimeterFrame.md
│ ├── Id3v2PrivateFrame.md
│ ├── Id3v2RelativeVolumeFrame.md
│ ├── Id3v2RelativeVolumeFrameChannelData.md
│ ├── Id3v2Settings.md
│ ├── Id3v2Synchronized.md
│ ├── Id3v2SynchronizedLyricsFrame.md
│ ├── Id3v2Tag.md
│ ├── Id3v2TagFooter.md
│ ├── Id3v2TagHeader.md
│ ├── Id3v2TermsOfUseFrame.md
│ ├── Id3v2TextInformationFrame.md
│ ├── Id3v2UniqueFileIdentifierFrame.md
│ ├── Id3v2UnknownFrame.md
│ ├── Id3v2UnsynchronizedLyricsFrame.md
│ ├── Id3v2UrlLinkFrame.md
│ ├── Id3v2UserTextInformationFrame.md
│ ├── Id3v2UserUrlLinkFrame.md
│ ├── InfoTag.md
│ ├── LocalFileAbstraction.md
│ ├── MatroskaFile.md
│ ├── MovieIdTag.md
│ ├── Mpeg4AppleAdditionalInfoBox.md
│ ├── Mpeg4AppleAnnotationBox.md
│ ├── Mpeg4AppleDataBox.md
│ ├── Mpeg4AppleElementaryStreamDescriptor.md
│ ├── Mpeg4AppleItemListBox.md
│ ├── Mpeg4AppleTag.md
│ ├── Mpeg4Box.md
│ ├── Mpeg4BoxHeader.md
│ ├── Mpeg4BoxType.md
│ ├── Mpeg4File.md
│ ├── Mpeg4FullBox.md
│ ├── Mpeg4IsoAudioSampleEntry.md
│ ├── Mpeg4IsoChunkLargeOffset.md
│ ├── Mpeg4IsoChunkOffsetBox.md
│ ├── Mpeg4IsoFreeSpaceBox.md
│ ├── Mpeg4IsoHandlerBox.md
│ ├── Mpeg4IsoMetaBox.md
│ ├── Mpeg4IsoMovieHeaderBox.md
│ ├── Mpeg4IsoSampleDescriptionBox.md
│ ├── Mpeg4IsoSampleEntry.md
│ ├── Mpeg4IsoSampleTableBox.md
│ ├── Mpeg4IsoUnknownSampleEntry.md
│ ├── Mpeg4IsoUserDataBox.md
│ ├── Mpeg4IsoVisualSampleEntry.md
│ ├── Mpeg4TextBox.md
│ ├── Mpeg4UnknownBox.md
│ ├── Mpeg4UrlBox.md
│ ├── MpegAudioFile.md
│ ├── MpegAudioFileSettings.md
│ ├── MpegAudioHeader.md
│ ├── MpegContainerFile.md
│ ├── MpegVbriHeader.md
│ ├── MpegVideoHeader.md
│ ├── MpegXingHeader.md
│ ├── NotImplementedError.md
│ ├── OggCodecFactory.md
│ ├── OggFile.md
│ ├── OggFileSettings.md
│ ├── OggOpusCodec.md
│ ├── OggTag.md
│ ├── OggTheoraCodec.md
│ ├── OggVorbisCodec.md
│ ├── Picture.md
│ ├── PictureLazy.md
│ ├── Properties.md
│ ├── RiffBitmapInfoHeader.md
│ ├── RiffFile.md
│ ├── RiffList.md
│ ├── RiffListTag.md
│ ├── RiffWaveFormatEx.md
│ ├── SandwichFile.md
│ ├── SandwichTag.md
│ ├── StartTag.md
│ ├── Tag.md
│ ├── UuidWrapper.md
│ ├── WaveFileSettings.md
│ ├── XiphComment.md
│ └── XiphPicture.md
├── enums
│ ├── ApeTagItemType.md
│ ├── AsfObjectDataType.md
│ ├── AsfObjectType.md
│ ├── AviStreamType.md
│ ├── FileAccessMode.md
│ ├── FlacBlockType.md
│ ├── Id3v2EventType.md
│ ├── Id3v2FrameClassType.md
│ ├── Id3v2FrameFlags.md
│ ├── Id3v2RelativeVolumeFrameChannelType.md
│ ├── Id3v2SynchronizedTextType.md
│ ├── Id3v2TagHeaderFlags.md
│ ├── Id3v2TimestampFormat.md
│ ├── MediaTypes.md
│ ├── Mpeg4AppleDataBoxFlagType.md
│ ├── MpegAudioChannelMode.md
│ ├── MpegVersion.md
│ ├── PictureType.md
│ ├── ReadStyle.md
│ ├── SeekOrigin.md
│ ├── StringType.md
│ └── TagTypes.md
├── interfaces
│ ├── IAudioCodec.md
│ ├── ICodec.md
│ ├── IDisposable.md
│ ├── IFileAbstraction.md
│ ├── ILazy.md
│ ├── ILosslessAudioCodec.md
│ ├── IOggCodec.md
│ ├── IPhotoCodec.md
│ ├── IPicture.md
│ ├── IRiffChunk.md
│ ├── ISandwichFile.md
│ ├── IStream.md
│ └── IVideoCodec.md
└── modules.md
├── package-lock.json
├── package.json
├── src
├── aac
│ ├── aacAudioHeader.ts
│ ├── aacFile.ts
│ └── aacFileSettings.ts
├── aiff
│ ├── aiffFile.ts
│ ├── aiffFileSettings.ts
│ └── aiffStreamHeader.ts
├── ape
│ ├── apeFile.ts
│ ├── apeFileSettings.ts
│ ├── apeStreamHeader.ts
│ ├── apeTag.ts
│ ├── apeTagFooter.ts
│ └── apeTagItem.ts
├── asf
│ ├── asfFile.ts
│ ├── asfTag.ts
│ ├── constants.ts
│ ├── objects
│ │ ├── baseObject.ts
│ │ ├── contentDescriptionObject.ts
│ │ ├── descriptorBase.ts
│ │ ├── extendedContentDescriptionObject.ts
│ │ ├── filePropertiesObject.ts
│ │ ├── headerExtensionObject.ts
│ │ ├── headerObject.ts
│ │ ├── metadataLibraryObject.ts
│ │ ├── paddingObject.ts
│ │ ├── streamPropertiesObject.ts
│ │ └── unknownObject.ts
│ └── readWriteUtils.ts
├── byteVector.ts
├── combinedTag.ts
├── ebml
│ ├── ebmlElement.ts
│ ├── ebmlParser.ts
│ ├── ebmlParserOptions.ts
│ └── ids.ts
├── errors.ts
├── file.ts
├── fileAbstraction.ts
├── flac
│ ├── flacBlock.ts
│ ├── flacFile.ts
│ ├── flacFileSettings.ts
│ ├── flacStreamHeader.ts
│ └── flacTag.ts
├── genres.ts
├── id3v1
│ └── id3v1Tag.ts
├── id3v2
│ ├── frameIdentifiers.ts
│ ├── frames
│ │ ├── attachmentFrame.ts
│ │ ├── commentsFrame.ts
│ │ ├── eventTimeCodeFrame.ts
│ │ ├── frame.ts
│ │ ├── frameFactory.ts
│ │ ├── frameHeader.ts
│ │ ├── musicCdIdentifierFrame.ts
│ │ ├── playCountFrame.ts
│ │ ├── popularimeterFrame.ts
│ │ ├── privateFrame.ts
│ │ ├── relativeVolumeFrame.ts
│ │ ├── synchronizedLyricsFrame.ts
│ │ ├── termsOfUseFrame.ts
│ │ ├── textInformationFrame.ts
│ │ ├── uniqueFileIdentifierFrame.ts
│ │ ├── unknownFrame.ts
│ │ ├── unsynchronizedLyricsFrame.ts
│ │ └── urlLinkFrame.ts
│ ├── id3v2ExtendedHeader.ts
│ ├── id3v2Settings.ts
│ ├── id3v2Tag.ts
│ ├── id3v2TagFooter.ts
│ ├── id3v2TagHeader.ts
│ ├── syncData.ts
│ └── utilTypes.ts
├── index.ts
├── interfaces.ts
├── matroska
│ ├── matroskaAttachment.ts
│ ├── matroskaFile.ts
│ ├── matroskaIds.ts
│ ├── matroskaTag.ts
│ ├── matroskaTagCollection.ts
│ ├── matroskaTagTarget.ts
│ ├── matroskaTagValue.ts
│ └── tracks
│ │ ├── audioTrack.ts
│ │ ├── track.ts
│ │ ├── trackFactory.ts
│ │ └── videoTrack.ts
├── mpeg
│ ├── mpegAudioFile.ts
│ ├── mpegAudioFileSettings.ts
│ ├── mpegAudioHeader.ts
│ ├── mpegContainerFile.ts
│ ├── mpegContainerFileSettings.ts
│ ├── mpegEnums.ts
│ ├── mpegVideoHeader.ts
│ ├── vbrHeader.ts
│ ├── vbriHeader.ts
│ └── xingHeader.ts
├── mpeg4
│ ├── appleTag.ts
│ ├── boxes
│ │ ├── appleAdditionalInfoBox.ts
│ │ ├── appleAnnotationBox.ts
│ │ ├── appleDataBox.ts
│ │ ├── appleElementaryStreamDescriptor.ts
│ │ ├── appleItemListBox.ts
│ │ ├── fullBox.ts
│ │ ├── isoAudioSampleEntry.ts
│ │ ├── isoChunkLargeOffsetBox.ts
│ │ ├── isoChunkOffsetBox.ts
│ │ ├── isoFreeSpaceBox.ts
│ │ ├── isoHandlerBox.ts
│ │ ├── isoMetaBox.ts
│ │ ├── isoMovieHeaderBox.ts
│ │ ├── isoSampleDescriptionBox.ts
│ │ ├── isoSampleEntry.ts
│ │ ├── isoSampleTableBox.ts
│ │ ├── isoUnknownSampleEntry.ts
│ │ ├── isoUserDataBox.ts
│ │ ├── isoVisualSampleEntry.ts
│ │ ├── mpeg4Box.ts
│ │ ├── textBox.ts
│ │ ├── unknownBox.ts
│ │ └── urlBox.ts
│ ├── descriptorTag.ts
│ ├── descriptorTagReader.ts
│ ├── mpeg4AudioTypes.ts
│ ├── mpeg4BoxFactory.ts
│ ├── mpeg4BoxHeader.ts
│ ├── mpeg4BoxRenderer.ts
│ ├── mpeg4BoxType.ts
│ ├── mpeg4File.ts
│ ├── mpeg4FileParser.ts
│ ├── mpeg4HandlerType.ts
│ └── mpeg4Utils.ts
├── ogg
│ ├── codecs
│ │ ├── codecFactory.ts
│ │ ├── iOggCodec.ts
│ │ ├── opus.ts
│ │ ├── theora.ts
│ │ └── vorbis.ts
│ ├── oggBitStream.ts
│ ├── oggFile.ts
│ ├── oggFileSettings.ts
│ ├── oggPage.ts
│ ├── oggPageHeader.ts
│ ├── oggPaginator.ts
│ └── oggTag.ts
├── picture.ts
├── properties.ts
├── riff
│ ├── avi
│ │ ├── aviHeader.ts
│ │ └── aviStream.ts
│ ├── aviFileSettings.ts
│ ├── divxTag.ts
│ ├── iRiffChunk.ts
│ ├── infoTag.ts
│ ├── movieIdTag.ts
│ ├── riffBitmapInfoHeader.ts
│ ├── riffChunk.ts
│ ├── riffFile.ts
│ ├── riffList.ts
│ ├── riffListTag.ts
│ ├── riffTags.ts
│ ├── riffWaveFormatEx.ts
│ └── waveFileSettings.ts
├── sandwich
│ ├── endTag.ts
│ ├── sandwichFile.ts
│ ├── sandwichTag.ts
│ ├── startTag.ts
│ └── tagParsers.ts
├── settings.ts
├── stream.ts
├── tag.ts
├── utils.ts
├── uuidWrapper.ts
└── xiph
│ ├── xiphComment.ts
│ ├── xiphPicture.ts
│ └── xiphSettings.ts
├── test-integration
├── .eslintrc.js
├── aac_fileTests.ts
├── aiff_fileTests.ts
├── ape_fileTests.ts
├── asf_fileTests.ts
├── avi_fileTests.ts
├── flac_fileTests.ts
├── matroska_fileTests.ts
├── mp3_id3v1_fileTests.ts
├── mp3_id3v24_fileTests.ts
├── mp3_id3v2_fileTests.ts
├── mp3_propertiesTest.ts
├── mpeg4_m4a_fileTests.ts
├── mpeg4_m4v_fileTests.ts
├── mpeg_fileTest.ts
├── ogg_opus_fileTests.ts
├── ogg_theora_fileTests.ts
├── ogg_vorbis_fileTests.ts
├── resources
│ ├── corruptSamples
│ │ ├── corrupt.aac
│ │ ├── corrupt.aif
│ │ ├── corrupt.avi
│ │ ├── corrupt.flac
│ │ ├── corrupt.m4a
│ │ ├── corrupt.mpg
│ │ ├── corrupt.ogg
│ │ ├── corrupt.wav
│ │ ├── corrupt.wma
│ │ ├── corruptMissingFlag.ogg
│ │ └── corruptNullTitleId3v2.mp3
│ └── samples
│ │ ├── apple_tags.m4a
│ │ ├── bgo_658920.m4a
│ │ ├── bgo_676934.m4a
│ │ ├── bgo_701689.m4a
│ │ ├── sample.aac
│ │ ├── sample.aif
│ │ ├── sample.ape
│ │ ├── sample.avi
│ │ ├── sample.flac
│ │ ├── sample.m4a
│ │ ├── sample.m4v
│ │ ├── sample.mkv
│ │ ├── sample.mp3
│ │ ├── sample.mpg
│ │ ├── sample.ogg
│ │ ├── sample.ogv
│ │ ├── sample.opus
│ │ ├── sample.wav
│ │ ├── sample.wma
│ │ ├── sample_gimp.gif
│ │ ├── sample_props_cbr.mp3
│ │ ├── sample_props_vbri.mp3
│ │ ├── sample_props_xingabr.mp3
│ │ ├── sample_props_xingcbr.mp3
│ │ ├── sample_props_xingvbr.mp3
│ │ ├── sample_replaygain.m4a
│ │ ├── sample_replaygain.mp3
│ │ ├── sample_teenytiny.gif
│ │ ├── sample_v1_only.mp3
│ │ ├── sample_v2_3_ext_header.mp3
│ │ ├── sample_v2_4_unsynch.mp3
│ │ └── sample_v2_only.mp3
├── tsconfig.json
├── utilities
│ ├── extendedFileTests.ts
│ ├── standardFileTests.ts
│ ├── testConstants.ts
│ └── utilities.ts
└── wav_fileTest.ts
├── test-unit
├── .eslintrc.js
├── aac
│ ├── aacAudioHeaderTests.ts
│ └── aacFileTests.ts
├── aiff
│ └── aiffStreamHeaderTests.ts
├── ape
│ ├── apeFileTests.ts
│ ├── apeStreamHeaderTests.ts
│ ├── apeTagFooterTests.ts
│ ├── apeTagItemTests.ts
│ └── apeTagTests.ts
├── asf
│ ├── asfTagTests.ts
│ ├── contentDescriptionObjectTests.ts
│ ├── descriptorBaseTests.ts
│ ├── extendedContentDescriptionObjectTests.ts
│ ├── filePropertiesObjectTests.ts
│ ├── headerExtensionObjectTests.ts
│ ├── headerObjectTests.ts
│ ├── metadataLibraryObjectTests.ts
│ ├── objectTests.ts
│ ├── paddingObjectTests.ts
│ ├── streamPropertiesObjectTests.ts
│ └── unknownObjectTests.ts
├── byteVectorConstructorTests.ts
├── byteVectorConversionTests.ts
├── byteVectorMethodTests.ts
├── combinedTagTests.ts
├── ebml
│ ├── ebmlElementTests.ts
│ └── ebmlParserTests.ts
├── fileAbstractionTests.ts
├── fileTests.ts
├── flac
│ ├── flacBlockTests.ts
│ ├── flacFileTests.ts
│ ├── flacStreamHeaderTests.ts
│ └── flacTagTests.ts
├── id3v1
│ └── id3v1TagTests.ts
├── id3v2
│ ├── attachmentsFrameTests.ts
│ ├── commentsFrameTests.ts
│ ├── eventTimeCodeFrameTests.ts
│ ├── frameConstructorTests.ts
│ ├── frameFactoryTests.ts
│ ├── frameHeaderTests.ts
│ ├── frameIdentifiersTests.ts
│ ├── frameTests.ts
│ ├── id3v2TagTests.ts
│ ├── musicCdIdentifierFrameTests.ts
│ ├── playCountFrameTests.ts
│ ├── popularimeterFrameTests.ts
│ ├── privateFrameTests.ts
│ ├── relativeVolumeFrameTests.ts
│ ├── syncDataTests.ts
│ ├── synchronizedLyricsFrameTests.ts
│ ├── tagExtendedHeaderTests.ts
│ ├── tagFooterTests.ts
│ ├── tagHeaderTests.ts
│ ├── termsOfUseFrameTests.ts
│ ├── textInformationFrameTests.ts
│ ├── uniqueFileIdentifierFrameTests.ts
│ ├── unknownFrameTests.ts
│ ├── unsynchronizedLyricsFrameTests.ts
│ ├── urlLinkFrameTests.ts
│ ├── userTextInformationFrameTests.ts
│ └── userUrlLinkFrameTests.ts
├── matroska
│ ├── audioTrackTests.ts
│ ├── matroskaAttachmentTests.ts
│ ├── matroskaTagCollectionTests.ts
│ ├── matroskaTagTargetTests.ts
│ ├── matroskaTagTests.ts
│ ├── matroskaTagValueTests.ts
│ ├── trackFactoryTests.ts
│ ├── utils.ts
│ └── videoTrackTests.ts
├── mpeg
│ ├── mpegAudioFileTests.ts
│ ├── mpegAudioHeaderTests.ts
│ ├── mpegContainerFileTests.ts
│ ├── mpegVideoHeaderTests.ts
│ ├── vbriHeaderTests.ts
│ └── xingHeaderTests.ts
├── mpeg4
│ ├── appleTagTests.ts
│ ├── mpeg4Tests.ts
│ └── mpeg4UtilsTests.ts
├── ogg
│ ├── codecFactoryTests.ts
│ ├── codecPackets.ts
│ ├── groupedCommentTests.ts
│ ├── oggPageHeaderTests.ts
│ ├── opusCodecTests.ts
│ ├── theoraCodecTests.ts
│ └── vorbisCodecTests.ts
├── pictureLazyTests.ts
├── pictureTests.ts
├── resources
│ └── testFile.txt
├── riff
│ ├── aviHeaderTests.ts
│ ├── aviStreamTests.ts
│ ├── divxTagTests.ts
│ ├── infoTagTests.ts
│ ├── movieIdTagTests.ts
│ ├── resources.ts
│ ├── riffBitmapInfoHeaderTests.ts
│ ├── riffFileTests.ts
│ ├── riffListTagTests.ts
│ ├── riffListTests.ts
│ └── riffWaveFormatExTests.ts
├── sandwich
│ ├── endTagTests.ts
│ ├── sandwichFileTests.ts
│ ├── sandwichTagTests.ts
│ └── startTagTests.ts
├── streamTest.ts
├── testConstants.ts
├── tsconfig.json
├── utilities
│ ├── propertyTests.ts
│ ├── testFile.ts
│ ├── testStream.ts
│ └── testers.ts
└── xiph
│ ├── resources.ts
│ ├── xiphCommentTests.ts
│ └── xiphPictureTests.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
64 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
65 | .idea/**
66 |
67 | # CMake
68 | cmake-build-*/
69 |
70 | # File-based project format
71 | *.iws
72 |
73 | # mpeltonen/sbt-idea plugin
74 | .idea_modules/
75 |
76 | # JIRA plugin
77 | atlassian-ide-plugin.xml
78 |
79 | # Crashlytics plugin (for Android Studio and IntelliJ)
80 | com_crashlytics_export_strings.xml
81 | crashlytics.properties
82 | crashlytics-build.properties
83 | fabric.properties
84 |
85 | # Ignore build output
86 | dist/**
87 |
88 | # Files created during test
89 | test*/resources/**/testFile_*
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/Tests__Unit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | project
4 |
5 | $PROJECT_DIR$/node_modules/mocha
6 | $PROJECT_DIR$
7 | true
8 | bdd
9 |
10 | DIRECTORY
11 | $PROJECT_DIR$/test-unit
12 | true
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.mocharc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extension": ["ts"],
3 | "recursive": true,
4 | "require": [
5 | "ts-node/register",
6 | "source-map-support/register"
7 | ],
8 | "slow": 1000,
9 | "timout": 3000,
10 | "ui": "mocha-typescript"
11 | }
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | ## Override the .gitignore to make sure dist
2 |
3 | # Ignore test files
4 | test-*
5 |
6 | # Ignore idea stuff
7 | .idea
8 |
9 | # Ignore NYC coverage output files
10 | .nyc_output/**
11 |
12 | # Output of 'npm pack'
13 | *.tgz
14 |
15 | # Doc output
16 | docs/**
--------------------------------------------------------------------------------
/.nycrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@istanbuljs/nyc-config-typescript"
3 | }
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 5.1.0-{branch}.{build}
2 |
3 | environment:
4 | nodejs_version: "14.21"
5 |
6 | install:
7 | - ps: Install-Product node $env:nodejs_version
8 | - npm install
9 |
10 | build_script:
11 | - npm run build
12 | - npm pack
13 |
14 | test_script:
15 | - npm run test-unit-with-coverage
16 |
17 | after_test:
18 | - npm run publish-coverage
19 |
20 | artifacts:
21 | - path: '*.tgz'
22 | name: NPM Package
23 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
--------------------------------------------------------------------------------
/docs/classes/AviFileSettings.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / AviFileSettings
2 |
3 | # Class: AviFileSettings
4 |
5 | This class contains settings related to AVI file operations. Open files will need to be re-read
6 | in order for changes to take effect.
7 |
8 | ## Table of contents
9 |
10 | ### Constructors
11 |
12 | - [constructor](AviFileSettings.md#constructor)
13 |
14 | ### Properties
15 |
16 | - [SUPPORTED\_TAG\_TYPES](AviFileSettings.md#supported_tag_types)
17 |
18 | ### Accessors
19 |
20 | - [defaultTagTypes](AviFileSettings.md#defaulttagtypes)
21 |
22 | ## Constructors
23 |
24 | ### constructor
25 |
26 | • **new AviFileSettings**()
27 |
28 | ## Properties
29 |
30 | ### SUPPORTED\_TAG\_TYPES
31 |
32 | ▪ `Static` `Readonly` **SUPPORTED\_TAG\_TYPES**: `number`
33 |
34 | The types of tags that are supported by AVI files.
35 |
36 | ## Accessors
37 |
38 | ### defaultTagTypes
39 |
40 | • `Static` `get` **defaultTagTypes**(): [`TagTypes`](../enums/TagTypes.md)
41 |
42 | Gets the default types of tags for an AVI file. When opening a file, if these tag types do
43 | not exist on the file, they will be created.
44 |
45 | #### Returns
46 |
47 | [`TagTypes`](../enums/TagTypes.md)
48 |
49 | • `Static` `set` **defaultTagTypes**(`value`): `void`
50 |
51 | Sets the default types of tags for an AVI file. When opening a file, if these tag types do
52 | not exist on the file, they will be created. See [SUPPORTED_TAG_TYPES](AviFileSettings.md#supported_tag_types) for a list of tag
53 | types that are supported by node-taglib-sharp for AVI files.
54 |
55 | #### Parameters
56 |
57 | | Name | Type |
58 | | :------ | :------ |
59 | | `value` | [`TagTypes`](../enums/TagTypes.md) |
60 |
61 | #### Returns
62 |
63 | `void`
64 |
--------------------------------------------------------------------------------
/docs/classes/CorruptFileError.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / CorruptFileError
2 |
3 | # Class: CorruptFileError
4 |
5 | Error class that indicates the file is likely corrupt.
6 |
7 | ## Hierarchy
8 |
9 | - `Error`
10 |
11 | ↳ **`CorruptFileError`**
12 |
13 | ## Table of contents
14 |
15 | ### Constructors
16 |
17 | - [constructor](CorruptFileError.md#constructor)
18 |
19 | ### Properties
20 |
21 | - [message](CorruptFileError.md#message)
22 | - [name](CorruptFileError.md#name)
23 | - [stack](CorruptFileError.md#stack)
24 | - [prepareStackTrace](CorruptFileError.md#preparestacktrace)
25 | - [stackTraceLimit](CorruptFileError.md#stacktracelimit)
26 |
27 | ### Methods
28 |
29 | - [captureStackTrace](CorruptFileError.md#capturestacktrace)
30 |
31 | ## Constructors
32 |
33 | ### constructor
34 |
35 | • **new CorruptFileError**(`msg?`)
36 |
37 | #### Parameters
38 |
39 | | Name | Type |
40 | | :------ | :------ |
41 | | `msg?` | `string` |
42 |
43 | #### Overrides
44 |
45 | Error.constructor
46 |
47 | ## Properties
48 |
49 | ### message
50 |
51 | • **message**: `string`
52 |
53 | #### Inherited from
54 |
55 | Error.message
56 |
57 | ___
58 |
59 | ### name
60 |
61 | • **name**: `string`
62 |
63 | #### Inherited from
64 |
65 | Error.name
66 |
67 | ___
68 |
69 | ### stack
70 |
71 | • `Optional` **stack**: `string`
72 |
73 | #### Inherited from
74 |
75 | Error.stack
76 |
77 | ___
78 |
79 | ### prepareStackTrace
80 |
81 | ▪ `Static` `Optional` **prepareStackTrace**: (`err`: `Error`, `stackTraces`: `CallSite`[]) => `any`
82 |
83 | #### Type declaration
84 |
85 | ▸ (`err`, `stackTraces`): `any`
86 |
87 | Optional override for formatting stack traces
88 |
89 | **`See`**
90 |
91 | https://v8.dev/docs/stack-trace-api#customizing-stack-traces
92 |
93 | ##### Parameters
94 |
95 | | Name | Type |
96 | | :------ | :------ |
97 | | `err` | `Error` |
98 | | `stackTraces` | `CallSite`[] |
99 |
100 | ##### Returns
101 |
102 | `any`
103 |
104 | #### Inherited from
105 |
106 | Error.prepareStackTrace
107 |
108 | ___
109 |
110 | ### stackTraceLimit
111 |
112 | ▪ `Static` **stackTraceLimit**: `number`
113 |
114 | #### Inherited from
115 |
116 | Error.stackTraceLimit
117 |
118 | ## Methods
119 |
120 | ### captureStackTrace
121 |
122 | ▸ `Static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void`
123 |
124 | Create .stack property on a target object
125 |
126 | #### Parameters
127 |
128 | | Name | Type |
129 | | :------ | :------ |
130 | | `targetObject` | `object` |
131 | | `constructorOpt?` | `Function` |
132 |
133 | #### Returns
134 |
135 | `void`
136 |
137 | #### Inherited from
138 |
139 | Error.captureStackTrace
140 |
--------------------------------------------------------------------------------
/docs/classes/Id3v2ExtendedHeader.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2ExtendedHeader
2 |
3 | # Class: Id3v2ExtendedHeader
4 |
5 | This class is a filler until support for reading and writing the ID3v2 extended header is
6 | implemented.
7 |
8 | ## Table of contents
9 |
10 | ### Accessors
11 |
12 | - [size](Id3v2ExtendedHeader.md#size)
13 |
14 | ### Methods
15 |
16 | - [fromData](Id3v2ExtendedHeader.md#fromdata)
17 | - [fromEmpty](Id3v2ExtendedHeader.md#fromempty)
18 |
19 | ## Accessors
20 |
21 | ### size
22 |
23 | • `get` **size**(): `number`
24 |
25 | Gets the size of the data on disk in bytes.
26 |
27 | #### Returns
28 |
29 | `number`
30 |
31 | ## Methods
32 |
33 | ### fromData
34 |
35 | ▸ `Static` **fromData**(`data`, `version`): [`Id3v2ExtendedHeader`](Id3v2ExtendedHeader.md)
36 |
37 | Constructs and initializes a new instance by reading the raw contents.
38 |
39 | #### Parameters
40 |
41 | | Name | Type | Description |
42 | | :------ | :------ | :------ |
43 | | `data` | [`ByteVector`](ByteVector.md) | Raw extended header structure |
44 | | `version` | `number` | ID3v2 version. Must be an unsigned 8-bit integer. |
45 |
46 | #### Returns
47 |
48 | [`Id3v2ExtendedHeader`](Id3v2ExtendedHeader.md)
49 |
50 | ___
51 |
52 | ### fromEmpty
53 |
54 | ▸ `Static` **fromEmpty**(): [`Id3v2ExtendedHeader`](Id3v2ExtendedHeader.md)
55 |
56 | Constructs and initializes a new instance with no contents.
57 |
58 | #### Returns
59 |
60 | [`Id3v2ExtendedHeader`](Id3v2ExtendedHeader.md)
61 |
--------------------------------------------------------------------------------
/docs/classes/Id3v2SynchronizedLyricsFrame.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2SynchronizedLyricsFrame
2 |
3 | # Class: Id3v2SynchronizedLyricsFrame
4 |
5 | This structure contains a single entry in a SynchronizedLyricsFrame object.
6 |
7 | ## Table of contents
8 |
9 | ### Constructors
10 |
11 | - [constructor](Id3v2SynchronizedLyricsFrame.md#constructor)
12 |
13 | ### Properties
14 |
15 | - [text](Id3v2SynchronizedLyricsFrame.md#text)
16 |
17 | ### Accessors
18 |
19 | - [time](Id3v2SynchronizedLyricsFrame.md#time)
20 |
21 | ### Methods
22 |
23 | - [clone](Id3v2SynchronizedLyricsFrame.md#clone)
24 | - [render](Id3v2SynchronizedLyricsFrame.md#render)
25 |
26 | ## Constructors
27 |
28 | ### constructor
29 |
30 | • **new Id3v2SynchronizedLyricsFrame**(`time`, `text`)
31 |
32 | Constructs and initializes a new instance with a specified time and text.
33 |
34 | #### Parameters
35 |
36 | | Name | Type | Description |
37 | | :------ | :------ | :------ |
38 | | `time` | `number` | Offset into the media that owns this element when this element should be displayed. See TimestampFormat for possible values. |
39 | | `text` | `string` | Text for the point in time |
40 |
41 | ## Properties
42 |
43 | ### text
44 |
45 | • **text**: `string`
46 |
47 | Text for the point in time represented by the current instance.
48 |
49 | ## Accessors
50 |
51 | ### time
52 |
53 | • `get` **time**(): `number`
54 |
55 | Gets time offset of the current instance. The specific format this text element is defined
56 | in SynchronizedLyricsFrame.format of the frame that owns this element.
57 |
58 | #### Returns
59 |
60 | `number`
61 |
62 | • `set` **time**(`value`): `void`
63 |
64 | Sets time offset of the current instance. The specific format this text element is defined
65 | in SynchronizedLyricsFrame.format of the frame that owns this element.
66 |
67 | #### Parameters
68 |
69 | | Name | Type | Description |
70 | | :------ | :------ | :------ |
71 | | `value` | `number` | Offset of the current instance, must be a safe |
72 |
73 | #### Returns
74 |
75 | `void`
76 |
77 | ## Methods
78 |
79 | ### clone
80 |
81 | ▸ **clone**(): [`Id3v2SynchronizedLyricsFrame`](Id3v2SynchronizedLyricsFrame.md)
82 |
83 | Creates a copy of this instance.
84 |
85 | #### Returns
86 |
87 | [`Id3v2SynchronizedLyricsFrame`](Id3v2SynchronizedLyricsFrame.md)
88 |
89 | ___
90 |
91 | ### render
92 |
93 | ▸ **render**(`encoding`): [`ByteVector`](ByteVector.md)
94 |
95 | Generates a raw byte representation of the frame for writing to a file.
96 |
97 | #### Parameters
98 |
99 | | Name | Type | Description |
100 | | :------ | :------ | :------ |
101 | | `encoding` | [`StringType`](../enums/StringType.md) | Encoding to use for encoding the text of the frame. |
102 |
103 | #### Returns
104 |
105 | [`ByteVector`](ByteVector.md)
106 |
--------------------------------------------------------------------------------
/docs/classes/MpegVbriHeader.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / MpegVbriHeader
2 |
3 | # Class: MpegVbriHeader
4 |
5 | Information about a variable bitrate MPEG audio stream encoded by the Fraunhofer encoder
6 |
7 | ## Hierarchy
8 |
9 | - `default`
10 |
11 | ↳ **`MpegVbriHeader`**
12 |
13 | ## Table of contents
14 |
15 | ### Accessors
16 |
17 | - [bitrateKilobytes](MpegVbriHeader.md#bitratekilobytes)
18 | - [durationMilliseconds](MpegVbriHeader.md#durationmilliseconds)
19 | - [totalBytes](MpegVbriHeader.md#totalbytes)
20 | - [totalFrames](MpegVbriHeader.md#totalframes)
21 |
22 | ### Methods
23 |
24 | - [fromFile](MpegVbriHeader.md#fromfile)
25 |
26 | ## Accessors
27 |
28 | ### bitrateKilobytes
29 |
30 | • `get` **bitrateKilobytes**(): `number`
31 |
32 | Gets the bitrate of the ile in kilobytes per second, if it could be calculated using the
33 | current instance. `undefined`, otherwise.
34 |
35 | #### Returns
36 |
37 | `number`
38 |
39 | #### Inherited from
40 |
41 | VbrHeader.bitrateKilobytes
42 |
43 | ___
44 |
45 | ### durationMilliseconds
46 |
47 | • `get` **durationMilliseconds**(): `number`
48 |
49 | Gets the duration of the file in milliseconds, if it could be calculated using the current
50 | instance. `undefined`, otherwise.
51 |
52 | #### Returns
53 |
54 | `number`
55 |
56 | #### Inherited from
57 |
58 | VbrHeader.durationMilliseconds
59 |
60 | ___
61 |
62 | ### totalBytes
63 |
64 | • `get` **totalBytes**(): `number`
65 |
66 | Gets the total size of the file in bytes, as indicated by the current instance.
67 |
68 | #### Returns
69 |
70 | `number`
71 |
72 | #### Inherited from
73 |
74 | VbrHeader.totalBytes
75 |
76 | ___
77 |
78 | ### totalFrames
79 |
80 | • `get` **totalFrames**(): `number`
81 |
82 | Gets the total number of frames in the file, as indicated by the current instance.
83 |
84 | #### Returns
85 |
86 | `number`
87 |
88 | #### Inherited from
89 |
90 | VbrHeader.totalFrames
91 |
92 | ## Methods
93 |
94 | ### fromFile
95 |
96 | ▸ `Static` **fromFile**(`file`, `mpegHeaderPosition`, `samplesPerFrame`, `samplesPerSecond`): [`MpegVbriHeader`](MpegVbriHeader.md)
97 |
98 | #### Parameters
99 |
100 | | Name | Type |
101 | | :------ | :------ |
102 | | `file` | [`File`](File.md) |
103 | | `mpegHeaderPosition` | `number` |
104 | | `samplesPerFrame` | `number` |
105 | | `samplesPerSecond` | `number` |
106 |
107 | #### Returns
108 |
109 | [`MpegVbriHeader`](MpegVbriHeader.md)
110 |
--------------------------------------------------------------------------------
/docs/classes/NotImplementedError.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / NotImplementedError
2 |
3 | # Class: NotImplementedError
4 |
5 | Error class that indicates a piece of functionality is not implemented in the current version.
6 |
7 | ## Hierarchy
8 |
9 | - `Error`
10 |
11 | ↳ **`NotImplementedError`**
12 |
13 | ## Table of contents
14 |
15 | ### Constructors
16 |
17 | - [constructor](NotImplementedError.md#constructor)
18 |
19 | ### Properties
20 |
21 | - [message](NotImplementedError.md#message)
22 | - [name](NotImplementedError.md#name)
23 | - [stack](NotImplementedError.md#stack)
24 | - [prepareStackTrace](NotImplementedError.md#preparestacktrace)
25 | - [stackTraceLimit](NotImplementedError.md#stacktracelimit)
26 |
27 | ### Methods
28 |
29 | - [captureStackTrace](NotImplementedError.md#capturestacktrace)
30 |
31 | ## Constructors
32 |
33 | ### constructor
34 |
35 | • **new NotImplementedError**(`message?`)
36 |
37 | #### Parameters
38 |
39 | | Name | Type |
40 | | :------ | :------ |
41 | | `message?` | `string` |
42 |
43 | #### Overrides
44 |
45 | Error.constructor
46 |
47 | ## Properties
48 |
49 | ### message
50 |
51 | • **message**: `string`
52 |
53 | #### Inherited from
54 |
55 | Error.message
56 |
57 | ___
58 |
59 | ### name
60 |
61 | • **name**: `string`
62 |
63 | #### Inherited from
64 |
65 | Error.name
66 |
67 | ___
68 |
69 | ### stack
70 |
71 | • `Optional` **stack**: `string`
72 |
73 | #### Inherited from
74 |
75 | Error.stack
76 |
77 | ___
78 |
79 | ### prepareStackTrace
80 |
81 | ▪ `Static` `Optional` **prepareStackTrace**: (`err`: `Error`, `stackTraces`: `CallSite`[]) => `any`
82 |
83 | #### Type declaration
84 |
85 | ▸ (`err`, `stackTraces`): `any`
86 |
87 | Optional override for formatting stack traces
88 |
89 | **`See`**
90 |
91 | https://v8.dev/docs/stack-trace-api#customizing-stack-traces
92 |
93 | ##### Parameters
94 |
95 | | Name | Type |
96 | | :------ | :------ |
97 | | `err` | `Error` |
98 | | `stackTraces` | `CallSite`[] |
99 |
100 | ##### Returns
101 |
102 | `any`
103 |
104 | #### Inherited from
105 |
106 | Error.prepareStackTrace
107 |
108 | ___
109 |
110 | ### stackTraceLimit
111 |
112 | ▪ `Static` **stackTraceLimit**: `number`
113 |
114 | #### Inherited from
115 |
116 | Error.stackTraceLimit
117 |
118 | ## Methods
119 |
120 | ### captureStackTrace
121 |
122 | ▸ `Static` **captureStackTrace**(`targetObject`, `constructorOpt?`): `void`
123 |
124 | Create .stack property on a target object
125 |
126 | #### Parameters
127 |
128 | | Name | Type |
129 | | :------ | :------ |
130 | | `targetObject` | `object` |
131 | | `constructorOpt?` | `Function` |
132 |
133 | #### Returns
134 |
135 | `void`
136 |
137 | #### Inherited from
138 |
139 | Error.captureStackTrace
140 |
--------------------------------------------------------------------------------
/docs/classes/OggCodecFactory.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / OggCodecFactory
2 |
3 | # Class: OggCodecFactory
4 |
5 | Factory for creating codecs from the first packet of the Ogg bitstream.
6 |
7 | **`Remarks`**
8 |
9 | By default, only codecs provided by the library will be matched. However, custom codec
10 | support can be added by using [addCodecProvider](OggCodecFactory.md#addcodecprovider).
11 |
12 | ## Table of contents
13 |
14 | ### Constructors
15 |
16 | - [constructor](OggCodecFactory.md#constructor)
17 |
18 | ### Methods
19 |
20 | - [addCodecProvider](OggCodecFactory.md#addcodecprovider)
21 | - [clearCustomProviders](OggCodecFactory.md#clearcustomproviders)
22 | - [getCodec](OggCodecFactory.md#getcodec)
23 |
24 | ## Constructors
25 |
26 | ### constructor
27 |
28 | • **new OggCodecFactory**()
29 |
30 | ## Methods
31 |
32 | ### addCodecProvider
33 |
34 | ▸ `Static` **addCodecProvider**(`provider`): `void`
35 |
36 | Adds a custom codec provider to try before using standard codec creation methods.
37 | Codec providers are used before standard methods so custom checking can be used and new
38 | formats can be added. They are executed in reverse order in which they are added.
39 |
40 | #### Parameters
41 |
42 | | Name | Type | Description |
43 | | :------ | :------ | :------ |
44 | | `provider` | [`OggCodecProvider`](../modules.md#oggcodecprovider) | Codec provider function * firstPacket: ByteVector First packet of the bitstream * returns IOggCodec if method was able to match the packet, falsy otherwise |
45 |
46 | #### Returns
47 |
48 | `void`
49 |
50 | ___
51 |
52 | ### clearCustomProviders
53 |
54 | ▸ `Static` **clearCustomProviders**(): `void`
55 |
56 | Clears the custom providers from the factory.
57 |
58 | #### Returns
59 |
60 | `void`
61 |
62 | ___
63 |
64 | ### getCodec
65 |
66 | ▸ `Static` **getCodec**(`packet`): [`IOggCodec`](../interfaces/IOggCodec.md)
67 |
68 | Determines the correc codec to use for a stream header packet.
69 |
70 | #### Parameters
71 |
72 | | Name | Type | Description |
73 | | :------ | :------ | :------ |
74 | | `packet` | [`ByteVector`](ByteVector.md) | First packet of an Ogg logical bitstream. |
75 |
76 | #### Returns
77 |
78 | [`IOggCodec`](../interfaces/IOggCodec.md)
79 |
--------------------------------------------------------------------------------
/docs/classes/OggFileSettings.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / OggFileSettings
2 |
3 | # Class: OggFileSettings
4 |
5 | This class contains settings related to Ogg file operations. Open files will need to be re-read
6 | in order for changes to take effect.
7 |
8 | ## Table of contents
9 |
10 | ### Constructors
11 |
12 | - [constructor](OggFileSettings.md#constructor)
13 |
14 | ### Accessors
15 |
16 | - [writeToAllComments](OggFileSettings.md#writetoallcomments)
17 |
18 | ## Constructors
19 |
20 | ### constructor
21 |
22 | • **new OggFileSettings**()
23 |
24 | ## Accessors
25 |
26 | ### writeToAllComments
27 |
28 | • `Static` `get` **writeToAllComments**(): `boolean`
29 |
30 | Gets whether changes to Ogg tag fields should be written to all Xiph comments or just the
31 | first Xiph comment in the file.
32 |
33 | **`Remarks`**
34 |
35 | Ogg files are required to have one Xiph comment per stream. In files with multiple
36 | streams, this means there are multiple Xiph comments per file.
37 |
38 | #### Returns
39 |
40 | `boolean`
41 |
42 | • `Static` `set` **writeToAllComments**(`value`): `void`
43 |
44 | Sets whether changes to Ogg tag fields should be written to all Xiph comments or just the
45 | first Xiph comment in the file.
46 |
47 | **`Remarks`**
48 |
49 | Ogg files are required to have one Xiph comment per stream. In files with multiple
50 | streams, this means there are multiple Xiph comments per file.
51 |
52 | #### Parameters
53 |
54 | | Name | Type |
55 | | :------ | :------ |
56 | | `value` | `boolean` |
57 |
58 | #### Returns
59 |
60 | `void`
61 |
--------------------------------------------------------------------------------
/docs/classes/UuidWrapper.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / UuidWrapper
2 |
3 | # Class: UuidWrapper
4 |
5 | Wrapper around the UUID package to make it easier to handle UUIDs.
6 |
7 | ## Table of contents
8 |
9 | ### Constructors
10 |
11 | - [constructor](UuidWrapper.md#constructor)
12 |
13 | ### Methods
14 |
15 | - [equals](UuidWrapper.md#equals)
16 | - [toBytes](UuidWrapper.md#tobytes)
17 | - [toString](UuidWrapper.md#tostring)
18 |
19 | ## Constructors
20 |
21 | ### constructor
22 |
23 | • **new UuidWrapper**(`source?`)
24 |
25 | Constructs an instance using either the supplied UUID or generating a new, random one.
26 |
27 | #### Parameters
28 |
29 | | Name | Type | Description |
30 | | :------ | :------ | :------ |
31 | | `source?` | `string` \| [`ByteVector`](ByteVector.md) | If provided, it is used as the bytes of the instance. If a falsy value is provided, a new v4 UUID will be generated. |
32 |
33 | ## Methods
34 |
35 | ### equals
36 |
37 | ▸ **equals**(`b`): `boolean`
38 |
39 | Determines whether this instance and another instance represent the same UUID.
40 |
41 | #### Parameters
42 |
43 | | Name | Type | Description |
44 | | :------ | :------ | :------ |
45 | | `b` | [`UuidWrapper`](UuidWrapper.md) | The other UUID to compare this one to. |
46 |
47 | #### Returns
48 |
49 | `boolean`
50 |
51 | ___
52 |
53 | ### toBytes
54 |
55 | ▸ **toBytes**(): [`ByteVector`](ByteVector.md)
56 |
57 | Gets the bytes that make up the UUID.
58 |
59 | #### Returns
60 |
61 | [`ByteVector`](ByteVector.md)
62 |
63 | ___
64 |
65 | ### toString
66 |
67 | ▸ **toString**(): `string`
68 |
69 | Gets a string representation of the UUID.
70 |
71 | #### Returns
72 |
73 | `string`
74 |
--------------------------------------------------------------------------------
/docs/classes/WaveFileSettings.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / WaveFileSettings
2 |
3 | # Class: WaveFileSettings
4 |
5 | This class contains settings related to WAV file operations. Open files will need to be re-read
6 | in order for changes to take effect.
7 |
8 | ## Table of contents
9 |
10 | ### Constructors
11 |
12 | - [constructor](WaveFileSettings.md#constructor)
13 |
14 | ### Properties
15 |
16 | - [SUPPORTED\_TAG\_TYPES](WaveFileSettings.md#supported_tag_types)
17 |
18 | ### Accessors
19 |
20 | - [defaultTagTypes](WaveFileSettings.md#defaulttagtypes)
21 |
22 | ## Constructors
23 |
24 | ### constructor
25 |
26 | • **new WaveFileSettings**()
27 |
28 | ## Properties
29 |
30 | ### SUPPORTED\_TAG\_TYPES
31 |
32 | ▪ `Static` `Readonly` **SUPPORTED\_TAG\_TYPES**: `number`
33 |
34 | The types of tags that are supported by WAV files.
35 |
36 | ## Accessors
37 |
38 | ### defaultTagTypes
39 |
40 | • `Static` `get` **defaultTagTypes**(): [`TagTypes`](../enums/TagTypes.md)
41 |
42 | Gets the default types of tags for an WAV file. When opening a file, if these tag types do
43 | not exist on the file, they will be created.
44 |
45 | #### Returns
46 |
47 | [`TagTypes`](../enums/TagTypes.md)
48 |
49 | • `Static` `set` **defaultTagTypes**(`value`): `void`
50 |
51 | Sets the default types of tags for an WAV file. When opening a file, if these tag types do
52 | not exist on the file, they will be created. See [SUPPORTED_TAG_TYPES](WaveFileSettings.md#supported_tag_types) for a list of tag
53 | types that are supported by node-taglib-sharp for WAV files.
54 |
55 | #### Parameters
56 |
57 | | Name | Type |
58 | | :------ | :------ |
59 | | `value` | [`TagTypes`](../enums/TagTypes.md) |
60 |
61 | #### Returns
62 |
63 | `void`
64 |
--------------------------------------------------------------------------------
/docs/enums/ApeTagItemType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / ApeTagItemType
2 |
3 | # Enumeration: ApeTagItemType
4 |
5 | Indicates the type of data stored in a [ApeTagItem](../classes/ApeTagItem.md) object.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Binary](ApeTagItemType.md#binary)
12 | - [Locator](ApeTagItemType.md#locator)
13 | - [Text](ApeTagItemType.md#text)
14 |
15 | ## Enumeration Members
16 |
17 | ### Binary
18 |
19 | • **Binary** = ``1``
20 |
21 | Item contains binary data
22 |
23 | ___
24 |
25 | ### Locator
26 |
27 | • **Locator** = ``2``
28 |
29 | Item contains a locator (file path/URL) for external information
30 |
31 | ___
32 |
33 | ### Text
34 |
35 | • **Text** = ``0``
36 |
37 | Item contains unicode text
38 |
--------------------------------------------------------------------------------
/docs/enums/AsfObjectDataType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / AsfObjectDataType
2 |
3 | # Enumeration: AsfObjectDataType
4 |
5 | Indicates the type of data stored in a ContentDescriptor or MetadataDescriptor object.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Bool](AsfObjectDataType.md#bool)
12 | - [Bytes](AsfObjectDataType.md#bytes)
13 | - [DWord](AsfObjectDataType.md#dword)
14 | - [Guid](AsfObjectDataType.md#guid)
15 | - [QWord](AsfObjectDataType.md#qword)
16 | - [Unicode](AsfObjectDataType.md#unicode)
17 | - [Word](AsfObjectDataType.md#word)
18 |
19 | ## Enumeration Members
20 |
21 | ### Bool
22 |
23 | • **Bool** = ``2``
24 |
25 | The descriptor contains a boolean value.
26 |
27 | ___
28 |
29 | ### Bytes
30 |
31 | • **Bytes** = ``1``
32 |
33 | The descriptor contains binary data.
34 |
35 | ___
36 |
37 | ### DWord
38 |
39 | • **DWord** = ``3``
40 |
41 | The descriptor contains a 4-byte DWORD value.
42 |
43 | ___
44 |
45 | ### Guid
46 |
47 | • **Guid** = ``6``
48 |
49 | The descriptor contains a 16-byte GUID value.
50 |
51 | ___
52 |
53 | ### QWord
54 |
55 | • **QWord** = ``4``
56 |
57 | The descriptor contains an 8-byte QWORD value.
58 |
59 | ___
60 |
61 | ### Unicode
62 |
63 | • **Unicode** = ``0``
64 |
65 | The descriptor contains Unicode (UTF-16LE) text.
66 |
67 | ___
68 |
69 | ### Word
70 |
71 | • **Word** = ``5``
72 |
73 | The descriptor contains a 2-byte WORD value.
74 |
--------------------------------------------------------------------------------
/docs/enums/AviStreamType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / AviStreamType
2 |
3 | # Enumeration: AviStreamType
4 |
5 | IDs for an AVI stream types.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [AudioStream](AviStreamType.md#audiostream)
12 | - [MidiStream](AviStreamType.md#midistream)
13 | - [TextStream](AviStreamType.md#textstream)
14 | - [VideoStream](AviStreamType.md#videostream)
15 |
16 | ## Enumeration Members
17 |
18 | ### AudioStream
19 |
20 | • **AudioStream** = ``1935963489``
21 |
22 | Audio Stream
23 |
24 | ___
25 |
26 | ### MidiStream
27 |
28 | • **MidiStream** = ``1919183213``
29 |
30 | MIDI Stream
31 |
32 | ___
33 |
34 | ### TextStream
35 |
36 | • **TextStream** = ``1937012852``
37 |
38 | Text stream
39 |
40 | ___
41 |
42 | ### VideoStream
43 |
44 | • **VideoStream** = ``1935960438``
45 |
46 | Video stream
47 |
--------------------------------------------------------------------------------
/docs/enums/FileAccessMode.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / FileAccessMode
2 |
3 | # Enumeration: FileAccessMode
4 |
5 | Specifies the type of file access operations currently permitted on an instance of [File](../classes/File.md)
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Closed](FileAccessMode.md#closed)
12 | - [Read](FileAccessMode.md#read)
13 | - [Write](FileAccessMode.md#write)
14 |
15 | ## Enumeration Members
16 |
17 | ### Closed
18 |
19 | • **Closed** = ``2``
20 |
21 | The file is closed for both read and write operations
22 |
23 | ___
24 |
25 | ### Read
26 |
27 | • **Read** = ``0``
28 |
29 | Read operations can be performed.
30 |
31 | ___
32 |
33 | ### Write
34 |
35 | • **Write** = ``1``
36 |
37 | Read and write operations can be performed
38 |
--------------------------------------------------------------------------------
/docs/enums/FlacBlockType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / FlacBlockType
2 |
3 | # Enumeration: FlacBlockType
4 |
5 | Specifies the contents of a FLAC block.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Application](FlacBlockType.md#application)
12 | - [CueSheet](FlacBlockType.md#cuesheet)
13 | - [Padding](FlacBlockType.md#padding)
14 | - [Picture](FlacBlockType.md#picture)
15 | - [SeekTable](FlacBlockType.md#seektable)
16 | - [StreamInfo](FlacBlockType.md#streaminfo)
17 | - [XiphComment](FlacBlockType.md#xiphcomment)
18 |
19 | ## Enumeration Members
20 |
21 | ### Application
22 |
23 | • **Application** = ``2``
24 |
25 | Block contains application data.
26 |
27 | ___
28 |
29 | ### CueSheet
30 |
31 | • **CueSheet** = ``5``
32 |
33 | Block contains a cue sheet.
34 |
35 | ___
36 |
37 | ### Padding
38 |
39 | • **Padding** = ``1``
40 |
41 | Block contains padding.
42 |
43 | ___
44 |
45 | ### Picture
46 |
47 | • **Picture** = ``6``
48 |
49 | Block contains a picture.
50 |
51 | ___
52 |
53 | ### SeekTable
54 |
55 | • **SeekTable** = ``3``
56 |
57 | Block contains a seek table.
58 |
59 | ___
60 |
61 | ### StreamInfo
62 |
63 | • **StreamInfo** = ``0``
64 |
65 | Block contains stream information.
66 |
67 | ___
68 |
69 | ### XiphComment
70 |
71 | • **XiphComment** = ``4``
72 |
73 | Block contains a Xiph comment.
74 |
--------------------------------------------------------------------------------
/docs/enums/Id3v2FrameFlags.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2FrameFlags
2 |
3 | # Enumeration: Id3v2FrameFlags
4 |
5 | Indicates the flags applied to a [Id3v2FrameHeader](../classes/Id3v2FrameHeader.md) object.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Compression](Id3v2FrameFlags.md#compression)
12 | - [DataLengthIndicator](Id3v2FrameFlags.md#datalengthindicator)
13 | - [Encryption](Id3v2FrameFlags.md#encryption)
14 | - [FileAlterPreservation](Id3v2FrameFlags.md#filealterpreservation)
15 | - [GroupingIdentity](Id3v2FrameFlags.md#groupingidentity)
16 | - [None](Id3v2FrameFlags.md#none)
17 | - [ReadOnly](Id3v2FrameFlags.md#readonly)
18 | - [TagAlterPreservation](Id3v2FrameFlags.md#tagalterpreservation)
19 | - [Unsynchronized](Id3v2FrameFlags.md#unsynchronized)
20 |
21 | ## Enumeration Members
22 |
23 | ### Compression
24 |
25 | • **Compression** = ``8``
26 |
27 | Frame data is compressed.
28 |
29 | ___
30 |
31 | ### DataLengthIndicator
32 |
33 | • **DataLengthIndicator** = ``1``
34 |
35 | Frame has a data length indicator.
36 |
37 | ___
38 |
39 | ### Encryption
40 |
41 | • **Encryption** = ``4``
42 |
43 | Frame data is encrypted.
44 |
45 | ___
46 |
47 | ### FileAlterPreservation
48 |
49 | • **FileAlterPreservation** = ``8192``
50 |
51 | Frame is to be deleted if the file is altered.
52 |
53 | ___
54 |
55 | ### GroupingIdentity
56 |
57 | • **GroupingIdentity** = ``64``
58 |
59 | Frame has a grouping identity.
60 |
61 | ___
62 |
63 | ### None
64 |
65 | • **None** = ``0``
66 |
67 | Header contains no flags.
68 |
69 | ___
70 |
71 | ### ReadOnly
72 |
73 | • **ReadOnly** = ``4096``
74 |
75 | Frame is read-only and should not be altered.
76 |
77 | ___
78 |
79 | ### TagAlterPreservation
80 |
81 | • **TagAlterPreservation** = ``16384``
82 |
83 | Frame is to be deleted if the tag is altered.
84 |
85 | ___
86 |
87 | ### Unsynchronized
88 |
89 | • **Unsynchronized** = ``2``
90 |
91 | Frame data has been unsynchronized using the ID3v2 unsynchronization scheme.
92 |
--------------------------------------------------------------------------------
/docs/enums/Id3v2RelativeVolumeFrameChannelType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2RelativeVolumeFrameChannelType
2 |
3 | # Enumeration: Id3v2RelativeVolumeFrameChannelType
4 |
5 | Type of channel data to get from or set to a RelativeVolumeFrame object
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [BackCenter](Id3v2RelativeVolumeFrameChannelType.md#backcenter)
12 | - [BackLeft](Id3v2RelativeVolumeFrameChannelType.md#backleft)
13 | - [BackRight](Id3v2RelativeVolumeFrameChannelType.md#backright)
14 | - [FrontCentre](Id3v2RelativeVolumeFrameChannelType.md#frontcentre)
15 | - [FrontLeft](Id3v2RelativeVolumeFrameChannelType.md#frontleft)
16 | - [FrontRight](Id3v2RelativeVolumeFrameChannelType.md#frontright)
17 | - [MasterVolume](Id3v2RelativeVolumeFrameChannelType.md#mastervolume)
18 | - [Other](Id3v2RelativeVolumeFrameChannelType.md#other)
19 | - [Subwoofer](Id3v2RelativeVolumeFrameChannelType.md#subwoofer)
20 |
21 | ## Enumeration Members
22 |
23 | ### BackCenter
24 |
25 | • **BackCenter** = ``7``
26 |
27 | Channel data for back center speaker
28 |
29 | ___
30 |
31 | ### BackLeft
32 |
33 | • **BackLeft** = ``5``
34 |
35 | Channel data for back left speaker
36 |
37 | ___
38 |
39 | ### BackRight
40 |
41 | • **BackRight** = ``4``
42 |
43 | Channel data for center right speaker
44 |
45 | ___
46 |
47 | ### FrontCentre
48 |
49 | • **FrontCentre** = ``6``
50 |
51 | Channel data for front center speaker
52 |
53 | ___
54 |
55 | ### FrontLeft
56 |
57 | • **FrontLeft** = ``3``
58 |
59 | Channel data for front left speaker
60 |
61 | ___
62 |
63 | ### FrontRight
64 |
65 | • **FrontRight** = ``2``
66 |
67 | Channel data for the front right speaker
68 |
69 | ___
70 |
71 | ### MasterVolume
72 |
73 | • **MasterVolume** = ``1``
74 |
75 | Channel data for the master volume
76 |
77 | ___
78 |
79 | ### Other
80 |
81 | • **Other** = ``0``
82 |
83 | Channel data for some other speaker
84 |
85 | ___
86 |
87 | ### Subwoofer
88 |
89 | • **Subwoofer** = ``8``
90 |
91 | Channel data for subwoofer
92 |
--------------------------------------------------------------------------------
/docs/enums/Id3v2SynchronizedTextType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2SynchronizedTextType
2 |
3 | # Enumeration: Id3v2SynchronizedTextType
4 |
5 | Specifies the type of text contained in a synchronized lyrics frame
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Chord](Id3v2SynchronizedTextType.md#chord)
12 | - [Events](Id3v2SynchronizedTextType.md#events)
13 | - [ImageUrls](Id3v2SynchronizedTextType.md#imageurls)
14 | - [Lyrics](Id3v2SynchronizedTextType.md#lyrics)
15 | - [Movement](Id3v2SynchronizedTextType.md#movement)
16 | - [Other](Id3v2SynchronizedTextType.md#other)
17 | - [TextTranscription](Id3v2SynchronizedTextType.md#texttranscription)
18 | - [Trivia](Id3v2SynchronizedTextType.md#trivia)
19 | - [WebpageUrls](Id3v2SynchronizedTextType.md#webpageurls)
20 |
21 | ## Enumeration Members
22 |
23 | ### Chord
24 |
25 | • **Chord** = ``5``
26 |
27 | Text contains chord changes that occur in the music
28 |
29 | ___
30 |
31 | ### Events
32 |
33 | • **Events** = ``4``
34 |
35 | Text describes events that occur
36 |
37 | ___
38 |
39 | ### ImageUrls
40 |
41 | • **ImageUrls** = ``8``
42 |
43 | Text contains URLs for relevant images
44 |
45 | ___
46 |
47 | ### Lyrics
48 |
49 | • **Lyrics** = ``1``
50 |
51 | Text contains lyrical data
52 |
53 | ___
54 |
55 | ### Movement
56 |
57 | • **Movement** = ``3``
58 |
59 | Text lists the movements in the piece
60 |
61 | ___
62 |
63 | ### Other
64 |
65 | • **Other** = ``0``
66 |
67 | Text is some other type of text
68 |
69 | ___
70 |
71 | ### TextTranscription
72 |
73 | • **TextTranscription** = ``2``
74 |
75 | Text contains a transcription
76 |
77 | ___
78 |
79 | ### Trivia
80 |
81 | • **Trivia** = ``6``
82 |
83 | Text contains trivia or "pop up" information about the media
84 |
85 | ___
86 |
87 | ### WebpageUrls
88 |
89 | • **WebpageUrls** = ``7``
90 |
91 | Text contains URLs for relevant webpages
92 |
--------------------------------------------------------------------------------
/docs/enums/Id3v2TagHeaderFlags.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2TagHeaderFlags
2 |
3 | # Enumeration: Id3v2TagHeaderFlags
4 |
5 | Indicates the flags applied to a [Id3v2TagHeader](../classes/Id3v2TagHeader.md) object.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [ExperimentalIndicator](Id3v2TagHeaderFlags.md#experimentalindicator)
12 | - [ExtendedHeader](Id3v2TagHeaderFlags.md#extendedheader)
13 | - [FooterPresent](Id3v2TagHeaderFlags.md#footerpresent)
14 | - [None](Id3v2TagHeaderFlags.md#none)
15 | - [Unsynchronization](Id3v2TagHeaderFlags.md#unsynchronization)
16 |
17 | ## Enumeration Members
18 |
19 | ### ExperimentalIndicator
20 |
21 | • **ExperimentalIndicator** = ``32``
22 |
23 | The tag described by the header is experimental.
24 |
25 | ___
26 |
27 | ### ExtendedHeader
28 |
29 | • **ExtendedHeader** = ``64``
30 |
31 | The tag described by the header contains an extended header.
32 |
33 | ___
34 |
35 | ### FooterPresent
36 |
37 | • **FooterPresent** = ``16``
38 |
39 | The tag described by the header contains a footer.
40 |
41 | ___
42 |
43 | ### None
44 |
45 | • **None** = ``0``
46 |
47 | The header contains no flags.
48 |
49 | ___
50 |
51 | ### Unsynchronization
52 |
53 | • **Unsynchronization** = ``128``
54 |
55 | The tag described by the header has been unsynchronized using the ID3v2 unsynchronization
56 | scheme.
57 |
--------------------------------------------------------------------------------
/docs/enums/Id3v2TimestampFormat.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Id3v2TimestampFormat
2 |
3 | # Enumeration: Id3v2TimestampFormat
4 |
5 | Specifies the timestamp format used by a few frame types.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [AbsoluteMilliseconds](Id3v2TimestampFormat.md#absolutemilliseconds)
12 | - [AbsoluteMpegFrames](Id3v2TimestampFormat.md#absolutempegframes)
13 | - [Unknown](Id3v2TimestampFormat.md#unknown)
14 |
15 | ## Enumeration Members
16 |
17 | ### AbsoluteMilliseconds
18 |
19 | • **AbsoluteMilliseconds** = ``2``
20 |
21 | Timestamp represents the number of milliseconds since the beginning of the audio stream
22 |
23 | ___
24 |
25 | ### AbsoluteMpegFrames
26 |
27 | • **AbsoluteMpegFrames** = ``1``
28 |
29 | Timestamp represents the number of MPEG frames since the beginning of the audio stream
30 |
31 | ___
32 |
33 | ### Unknown
34 |
35 | • **Unknown** = ``0``
36 |
37 | Timestamp is of unknown format
38 |
--------------------------------------------------------------------------------
/docs/enums/MediaTypes.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / MediaTypes
2 |
3 | # Enumeration: MediaTypes
4 |
5 | Indicates the types o media represented by a [ICodec](../interfaces/ICodec.md) or [Properties](../classes/Properties.md). These values
6 | can be combined to represent multiple media types.
7 |
8 | ## Table of contents
9 |
10 | ### Enumeration Members
11 |
12 | - [Audio](MediaTypes.md#audio)
13 | - [LosslessAudio](MediaTypes.md#losslessaudio)
14 | - [None](MediaTypes.md#none)
15 | - [Photo](MediaTypes.md#photo)
16 | - [Text](MediaTypes.md#text)
17 | - [Video](MediaTypes.md#video)
18 |
19 | ## Enumeration Members
20 |
21 | ### Audio
22 |
23 | • **Audio** = ``1``
24 |
25 | Audio is present
26 |
27 | ___
28 |
29 | ### LosslessAudio
30 |
31 | • **LosslessAudio** = ``17``
32 |
33 | Lossless audio is present. This also implies audio is present.
34 |
35 | ___
36 |
37 | ### None
38 |
39 | • **None** = ``0``
40 |
41 | No media is present
42 |
43 | ___
44 |
45 | ### Photo
46 |
47 | • **Photo** = ``4``
48 |
49 | A photo is present
50 |
51 | ___
52 |
53 | ### Text
54 |
55 | • **Text** = ``8``
56 |
57 | Text is present
58 |
59 | ___
60 |
61 | ### Video
62 |
63 | • **Video** = ``2``
64 |
65 | Video is present
66 |
--------------------------------------------------------------------------------
/docs/enums/Mpeg4AppleDataBoxFlagType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / Mpeg4AppleDataBoxFlagType
2 |
3 | # Enumeration: Mpeg4AppleDataBoxFlagType
4 |
5 | Specifies the type of data contained in a box.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [ContainsBmpData](Mpeg4AppleDataBoxFlagType.md#containsbmpdata)
12 | - [ContainsData](Mpeg4AppleDataBoxFlagType.md#containsdata)
13 | - [ContainsJpegData](Mpeg4AppleDataBoxFlagType.md#containsjpegdata)
14 | - [ContainsPngData](Mpeg4AppleDataBoxFlagType.md#containspngdata)
15 | - [ContainsText](Mpeg4AppleDataBoxFlagType.md#containstext)
16 | - [ForTempo](Mpeg4AppleDataBoxFlagType.md#fortempo)
17 |
18 | ## Enumeration Members
19 |
20 | ### ContainsBmpData
21 |
22 | • **ContainsBmpData** = ``27``
23 |
24 | The box contains a raw BMP image.
25 |
26 | ___
27 |
28 | ### ContainsData
29 |
30 | • **ContainsData** = ``0``
31 |
32 | The box contains binary data.
33 |
34 | ___
35 |
36 | ### ContainsJpegData
37 |
38 | • **ContainsJpegData** = ``13``
39 |
40 | The box contains a raw JPEG image.
41 |
42 | ___
43 |
44 | ### ContainsPngData
45 |
46 | • **ContainsPngData** = ``14``
47 |
48 | The box contains a raw PNG image.
49 |
50 | ___
51 |
52 | ### ContainsText
53 |
54 | • **ContainsText** = ``1``
55 |
56 | The box contains UTF-8 text.
57 |
58 | ___
59 |
60 | ### ForTempo
61 |
62 | • **ForTempo** = ``21``
63 |
64 | The box contains data for a tempo box.
65 |
--------------------------------------------------------------------------------
/docs/enums/MpegAudioChannelMode.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / MpegAudioChannelMode
2 |
3 | # Enumeration: MpegAudioChannelMode
4 |
5 | Indicates the MPEG audio channel mode of a file or stream.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [DualChannel](MpegAudioChannelMode.md#dualchannel)
12 | - [JointStereo](MpegAudioChannelMode.md#jointstereo)
13 | - [SingleChannel](MpegAudioChannelMode.md#singlechannel)
14 | - [Stereo](MpegAudioChannelMode.md#stereo)
15 |
16 | ## Enumeration Members
17 |
18 | ### DualChannel
19 |
20 | • **DualChannel** = ``2``
21 |
22 | Dual Channel Mono
23 |
24 | ___
25 |
26 | ### JointStereo
27 |
28 | • **JointStereo** = ``1``
29 |
30 | Joint Stereo
31 |
32 | ___
33 |
34 | ### SingleChannel
35 |
36 | • **SingleChannel** = ``3``
37 |
38 | Single Channel Mono
39 |
40 | ___
41 |
42 | ### Stereo
43 |
44 | • **Stereo** = ``0``
45 |
46 | Stereo
47 |
--------------------------------------------------------------------------------
/docs/enums/MpegVersion.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / MpegVersion
2 |
3 | # Enumeration: MpegVersion
4 |
5 | Indicates the MPEG version of a file or stream.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Unknown](MpegVersion.md#unknown)
12 | - [Version1](MpegVersion.md#version1)
13 | - [Version2](MpegVersion.md#version2)
14 | - [Version25](MpegVersion.md#version25)
15 |
16 | ## Enumeration Members
17 |
18 | ### Unknown
19 |
20 | • **Unknown** = ``-1``
21 |
22 | Unknown version
23 |
24 | ___
25 |
26 | ### Version1
27 |
28 | • **Version1** = ``0``
29 |
30 | MPEG-1
31 |
32 | ___
33 |
34 | ### Version2
35 |
36 | • **Version2** = ``1``
37 |
38 | MPEG-2
39 |
40 | ___
41 |
42 | ### Version25
43 |
44 | • **Version25** = ``2``
45 |
46 | MPEG-2.5
47 |
--------------------------------------------------------------------------------
/docs/enums/ReadStyle.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / ReadStyle
2 |
3 | # Enumeration: ReadStyle
4 |
5 | Specifies the options to use when reading the media. Can be treated as flags.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Average](ReadStyle.md#average)
12 | - [None](ReadStyle.md#none)
13 | - [PictureLazy](ReadStyle.md#picturelazy)
14 |
15 | ## Enumeration Members
16 |
17 | ### Average
18 |
19 | • **Average** = ``2``
20 |
21 | The media properties will be read with average accuracy.
22 |
23 | ___
24 |
25 | ### None
26 |
27 | • **None** = ``0``
28 |
29 | The media properties will not be read.
30 |
31 | ___
32 |
33 | ### PictureLazy
34 |
35 | • **PictureLazy** = ``4``
36 |
37 | Use the [PictureLazy](../classes/PictureLazy.md) class in the property [pictures](../classes/Tag.md#pictures). This will avoid
38 | loading picture content when reading the tag. Picture will be read lazily, when the picture
39 | content is accessed.
40 |
--------------------------------------------------------------------------------
/docs/enums/SeekOrigin.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / SeekOrigin
2 |
3 | # Enumeration: SeekOrigin
4 |
5 | Indicates there the seek operation should begin.
6 |
7 | ## Table of contents
8 |
9 | ### Enumeration Members
10 |
11 | - [Begin](SeekOrigin.md#begin)
12 | - [Current](SeekOrigin.md#current)
13 | - [End](SeekOrigin.md#end)
14 |
15 | ## Enumeration Members
16 |
17 | ### Begin
18 |
19 | • **Begin** = ``0``
20 |
21 | Seek should begin at the start of the file.
22 |
23 | ___
24 |
25 | ### Current
26 |
27 | • **Current** = ``1``
28 |
29 | Seek should begin at the current position in the file.
30 |
31 | ___
32 |
33 | ### End
34 |
35 | • **End** = ``2``
36 |
37 | Seek should begin at the end of the file.
38 |
--------------------------------------------------------------------------------
/docs/enums/StringType.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / StringType
2 |
3 | # Enumeration: StringType
4 |
5 | **`Summary`**
6 |
7 | Specifies the text encoding used when converting betweenInclusive a string and a
8 | [ByteVector](../classes/ByteVector.md).
9 |
10 | **`Remarks`**
11 |
12 | This enumeration is used by [fromString](../classes/ByteVector.md#fromstring) and
13 | [toString](../classes/ByteVector.md#tostring)
14 |
15 | ## Table of contents
16 |
17 | ### Enumeration Members
18 |
19 | - [Hex](StringType.md#hex)
20 | - [Latin1](StringType.md#latin1)
21 | - [UTF16](StringType.md#utf16)
22 | - [UTF16BE](StringType.md#utf16be)
23 | - [UTF16LE](StringType.md#utf16le)
24 | - [UTF8](StringType.md#utf8)
25 |
26 | ## Enumeration Members
27 |
28 | ### Hex
29 |
30 | • **Hex** = ``5``
31 |
32 | **`Summary`**
33 |
34 | The string is to be encoded as a hex string for each byte (eg, 0x00, 0x12, 0xAF).
35 | Intended to be used for debugging purposes, only.
36 |
37 | ___
38 |
39 | ### Latin1
40 |
41 | • **Latin1** = ``0``
42 |
43 | **`Summary`**
44 |
45 | The string is to be Latin-1 encoded.
46 |
47 | ___
48 |
49 | ### UTF16
50 |
51 | • **UTF16** = ``1``
52 |
53 | **`Summary`**
54 |
55 | The string is to be UTF-16 encoded.
56 |
57 | ___
58 |
59 | ### UTF16BE
60 |
61 | • **UTF16BE** = ``2``
62 |
63 | **`Summary`**
64 |
65 | The string is to be UTF-16BE encoded.
66 |
67 | ___
68 |
69 | ### UTF16LE
70 |
71 | • **UTF16LE** = ``4``
72 |
73 | **`Summary`**
74 |
75 | The string is to be UTF-16LE encoded.
76 |
77 | ___
78 |
79 | ### UTF8
80 |
81 | • **UTF8** = ``3``
82 |
83 | **`Summary`**
84 |
85 | The string is to be UTF-8 encoded.
86 |
--------------------------------------------------------------------------------
/docs/interfaces/IAudioCodec.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IAudioCodec
2 |
3 | # Interface: IAudioCodec
4 |
5 | Interface that inherits the common codec information and adds audio-specific information.
6 | When dealing with an [ICodec](ICodec.md), if [mediaTypes](ICodec.md#mediatypes) contains
7 | [Audio](../enums/MediaTypes.md#audio), it is safe to assume that the object also inherits [IAudioCodec](IAudioCodec.md)
8 | and can be recast without issue.
9 |
10 | ## Hierarchy
11 |
12 | - [`ICodec`](ICodec.md)
13 |
14 | ↳ **`IAudioCodec`**
15 |
16 | ↳↳ [`ILosslessAudioCodec`](ILosslessAudioCodec.md)
17 |
18 | ## Implemented by
19 |
20 | - [`Mpeg4IsoAudioSampleEntry`](../classes/Mpeg4IsoAudioSampleEntry.md)
21 | - [`MpegAudioHeader`](../classes/MpegAudioHeader.md)
22 | - [`OggOpusCodec`](../classes/OggOpusCodec.md)
23 | - [`OggVorbisCodec`](../classes/OggVorbisCodec.md)
24 |
25 | ## Table of contents
26 |
27 | ### Properties
28 |
29 | - [audioBitrate](IAudioCodec.md#audiobitrate)
30 | - [audioChannels](IAudioCodec.md#audiochannels)
31 | - [audioSampleRate](IAudioCodec.md#audiosamplerate)
32 | - [description](IAudioCodec.md#description)
33 | - [durationMilliseconds](IAudioCodec.md#durationmilliseconds)
34 | - [mediaTypes](IAudioCodec.md#mediatypes)
35 |
36 | ## Properties
37 |
38 | ### audioBitrate
39 |
40 | • **audioBitrate**: `number`
41 |
42 | Bitrate of the audio in kilobits per second represented by the current instance.
43 |
44 | ___
45 |
46 | ### audioChannels
47 |
48 | • **audioChannels**: `number`
49 |
50 | Number of channels in the audio represented by the current instance.
51 |
52 | ___
53 |
54 | ### audioSampleRate
55 |
56 | • **audioSampleRate**: `number`
57 |
58 | Sample rate of the audio represented by the current instance.
59 |
60 | ___
61 |
62 | ### description
63 |
64 | • **description**: `string`
65 |
66 | Gets a text description of the media represented by the current instance.
67 |
68 | #### Inherited from
69 |
70 | [ICodec](ICodec.md).[description](ICodec.md#description)
71 |
72 | ___
73 |
74 | ### durationMilliseconds
75 |
76 | • **durationMilliseconds**: `number`
77 |
78 | Duration of the media in milliseconds represented by the current instance.
79 |
80 | **`TODO`**
81 |
82 | Ensure milliseconds is the right way to interpret this field
83 |
84 | #### Inherited from
85 |
86 | [ICodec](ICodec.md).[durationMilliseconds](ICodec.md#durationmilliseconds)
87 |
88 | ___
89 |
90 | ### mediaTypes
91 |
92 | • **mediaTypes**: [`MediaTypes`](../enums/MediaTypes.md)
93 |
94 | Types of media represented by the current instance, bitwise combined.
95 |
96 | #### Inherited from
97 |
98 | [ICodec](ICodec.md).[mediaTypes](ICodec.md#mediatypes)
99 |
--------------------------------------------------------------------------------
/docs/interfaces/ICodec.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / ICodec
2 |
3 | # Interface: ICodec
4 |
5 | Interface that provides basic information common to all media codecs
6 |
7 | ## Hierarchy
8 |
9 | - **`ICodec`**
10 |
11 | ↳ [`IAudioCodec`](IAudioCodec.md)
12 |
13 | ↳ [`IVideoCodec`](IVideoCodec.md)
14 |
15 | ↳ [`IPhotoCodec`](IPhotoCodec.md)
16 |
17 | ↳ [`IOggCodec`](IOggCodec.md)
18 |
19 | ## Table of contents
20 |
21 | ### Properties
22 |
23 | - [description](ICodec.md#description)
24 | - [durationMilliseconds](ICodec.md#durationmilliseconds)
25 | - [mediaTypes](ICodec.md#mediatypes)
26 |
27 | ## Properties
28 |
29 | ### description
30 |
31 | • **description**: `string`
32 |
33 | Gets a text description of the media represented by the current instance.
34 |
35 | ___
36 |
37 | ### durationMilliseconds
38 |
39 | • **durationMilliseconds**: `number`
40 |
41 | Duration of the media in milliseconds represented by the current instance.
42 |
43 | **`TODO`**
44 |
45 | Ensure milliseconds is the right way to interpret this field
46 |
47 | ___
48 |
49 | ### mediaTypes
50 |
51 | • **mediaTypes**: [`MediaTypes`](../enums/MediaTypes.md)
52 |
53 | Types of media represented by the current instance, bitwise combined.
54 |
--------------------------------------------------------------------------------
/docs/interfaces/IDisposable.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IDisposable
2 |
3 | # Interface: IDisposable
4 |
5 | Interface for objects that can (and should) be disposed after they are no longer needed.
6 |
7 | ## Implemented by
8 |
9 | - [`File`](../classes/File.md)
10 |
11 | ## Table of contents
12 |
13 | ### Methods
14 |
15 | - [dispose](IDisposable.md#dispose)
16 |
17 | ## Methods
18 |
19 | ### dispose
20 |
21 | ▸ **dispose**(): `void`
22 |
23 | Disposes the current instance.
24 |
25 | #### Returns
26 |
27 | `void`
28 |
--------------------------------------------------------------------------------
/docs/interfaces/IFileAbstraction.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IFileAbstraction
2 |
3 | # Interface: IFileAbstraction
4 |
5 | This interface provides abstracted access to a file. It permits access to non-standard file
6 | systems and data retrieval methods.
7 |
8 | ## Implemented by
9 |
10 | - [`LocalFileAbstraction`](../classes/LocalFileAbstraction.md)
11 |
12 | ## Table of contents
13 |
14 | ### Properties
15 |
16 | - [name](IFileAbstraction.md#name)
17 | - [readStream](IFileAbstraction.md#readstream)
18 | - [writeStream](IFileAbstraction.md#writestream)
19 |
20 | ### Methods
21 |
22 | - [closeStream](IFileAbstraction.md#closestream)
23 |
24 | ## Properties
25 |
26 | ### name
27 |
28 | • **name**: `string`
29 |
30 | Name or identifier used by the implementation
31 |
32 | **`Remarks`**
33 |
34 | This value would typically represent a path or URL to be used when identifying
35 | the file system, but it could be any valid as appropriate for the implementation.
36 |
37 | ___
38 |
39 | ### readStream
40 |
41 | • **readStream**: [`IStream`](IStream.md)
42 |
43 | Readable, seekable stream for the file referenced by the current instance.
44 |
45 | **`Remarks`**
46 |
47 | This property is typically used when constructing an instance of [File](../classes/File.md).
48 | Upon completion of the constructor [closeStream](IFileAbstraction.md#closestream) will be called to close the stream.
49 | If the stream is to be reused after this point, [closeStream](IFileAbstraction.md#closestream) should be implemented
50 | in a way to keep it open.
51 |
52 | ___
53 |
54 | ### writeStream
55 |
56 | • **writeStream**: [`IStream`](IStream.md)
57 |
58 | Writable, seekable stream for the file referenced by the current instance.
59 |
60 | **`Remarks`**
61 |
62 | This property is typically used when saving a file with [save](../classes/File.md#save). Upon
63 | completion of the method, [closeStream](IFileAbstraction.md#closestream) will be called to close the stream. If the
64 | stream is to be reused after this point, [closeStream](IFileAbstraction.md#closestream) should be implemented in a way
65 | to keep it open
66 |
67 | ## Methods
68 |
69 | ### closeStream
70 |
71 | ▸ **closeStream**(`stream`): `void`
72 |
73 | Closes a stream created by the current instance.
74 |
75 | #### Parameters
76 |
77 | | Name | Type | Description |
78 | | :------ | :------ | :------ |
79 | | `stream` | [`IStream`](IStream.md) | Stream created by the current instance. |
80 |
81 | #### Returns
82 |
83 | `void`
84 |
--------------------------------------------------------------------------------
/docs/interfaces/ILazy.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / ILazy
2 |
3 | # Interface: ILazy
4 |
5 | Interface for objects that can be lazily loaded.
6 |
7 | ## Implemented by
8 |
9 | - [`FlacBlock`](../classes/FlacBlock.md)
10 | - [`PictureLazy`](../classes/PictureLazy.md)
11 | - [`RiffList`](../classes/RiffList.md)
12 | - [`XiphPicture`](../classes/XiphPicture.md)
13 |
14 | ## Table of contents
15 |
16 | ### Properties
17 |
18 | - [isLoaded](ILazy.md#isloaded)
19 |
20 | ### Methods
21 |
22 | - [load](ILazy.md#load)
23 |
24 | ## Properties
25 |
26 | ### isLoaded
27 |
28 | • **isLoaded**: `boolean`
29 |
30 | Gets whether the object has been loaded.
31 |
32 | ## Methods
33 |
34 | ### load
35 |
36 | ▸ **load**(): `void`
37 |
38 | Loads the object.
39 |
40 | #### Returns
41 |
42 | `void`
43 |
--------------------------------------------------------------------------------
/docs/interfaces/IPhotoCodec.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IPhotoCodec
2 |
3 | # Interface: IPhotoCodec
4 |
5 | Interface that inherits the common codec information and adds photo-specific information.
6 | When dealing with an [ICodec](ICodec.md), if [mediaTypes](ICodec.md#mediatypes) contains
7 | [Photo](../enums/MediaTypes.md#photo), it is safe to assume that the object also inherits [IPhotoCodec](IPhotoCodec.md)
8 | and can be recast without issue.
9 |
10 | ## Hierarchy
11 |
12 | - [`ICodec`](ICodec.md)
13 |
14 | ↳ **`IPhotoCodec`**
15 |
16 | ## Implemented by
17 |
18 | - [`Properties`](../classes/Properties.md)
19 |
20 | ## Table of contents
21 |
22 | ### Properties
23 |
24 | - [description](IPhotoCodec.md#description)
25 | - [durationMilliseconds](IPhotoCodec.md#durationmilliseconds)
26 | - [mediaTypes](IPhotoCodec.md#mediatypes)
27 | - [photoHeight](IPhotoCodec.md#photoheight)
28 | - [photoQuality](IPhotoCodec.md#photoquality)
29 | - [photoWidth](IPhotoCodec.md#photowidth)
30 |
31 | ## Properties
32 |
33 | ### description
34 |
35 | • **description**: `string`
36 |
37 | Gets a text description of the media represented by the current instance.
38 |
39 | #### Inherited from
40 |
41 | [ICodec](ICodec.md).[description](ICodec.md#description)
42 |
43 | ___
44 |
45 | ### durationMilliseconds
46 |
47 | • **durationMilliseconds**: `number`
48 |
49 | Duration of the media in milliseconds represented by the current instance.
50 |
51 | **`TODO`**
52 |
53 | Ensure milliseconds is the right way to interpret this field
54 |
55 | #### Inherited from
56 |
57 | [ICodec](ICodec.md).[durationMilliseconds](ICodec.md#durationmilliseconds)
58 |
59 | ___
60 |
61 | ### mediaTypes
62 |
63 | • **mediaTypes**: [`MediaTypes`](../enums/MediaTypes.md)
64 |
65 | Types of media represented by the current instance, bitwise combined.
66 |
67 | #### Inherited from
68 |
69 | [ICodec](ICodec.md).[mediaTypes](ICodec.md#mediatypes)
70 |
71 | ___
72 |
73 | ### photoHeight
74 |
75 | • **photoHeight**: `number`
76 |
77 | Height of the photo in pixels represented by the current instance.
78 |
79 | ___
80 |
81 | ### photoQuality
82 |
83 | • **photoQuality**: `number`
84 |
85 | Format-specific quality indicator of the photo represented by the current instance.
86 | A value of `0` means there was no quality indicator for the format or file.
87 |
88 | ___
89 |
90 | ### photoWidth
91 |
92 | • **photoWidth**: `number`
93 |
94 | Width of the photo in pixels represented by the current instance.
95 |
--------------------------------------------------------------------------------
/docs/interfaces/IPicture.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IPicture
2 |
3 | # Interface: IPicture
4 |
5 | Interface that provides generic information about a picture, including its contents, as used by
6 | various formats.
7 |
8 | ## Implemented by
9 |
10 | - [`Id3v2AttachmentFrame`](../classes/Id3v2AttachmentFrame.md)
11 | - [`Picture`](../classes/Picture.md)
12 | - [`PictureLazy`](../classes/PictureLazy.md)
13 | - [`XiphPicture`](../classes/XiphPicture.md)
14 |
15 | ## Table of contents
16 |
17 | ### Properties
18 |
19 | - [data](IPicture.md#data)
20 | - [description](IPicture.md#description)
21 | - [filename](IPicture.md#filename)
22 | - [mimeType](IPicture.md#mimetype)
23 | - [type](IPicture.md#type)
24 |
25 | ## Properties
26 |
27 | ### data
28 |
29 | • **data**: [`ByteVector`](../classes/ByteVector.md)
30 |
31 | Gets and sets the picture data stored in the current instance.
32 |
33 | ___
34 |
35 | ### description
36 |
37 | • **description**: `string`
38 |
39 | Gets and sets a description of the picture stored in the current instance. Optional.
40 |
41 | ___
42 |
43 | ### filename
44 |
45 | • **filename**: `string`
46 |
47 | Gets and sets a filename of the picture stored in the current instance. Optional.
48 |
49 | ___
50 |
51 | ### mimeType
52 |
53 | • **mimeType**: `string`
54 |
55 | Gets and sets the mime-type of the picture data stored in the current instance.
56 |
57 | ___
58 |
59 | ### type
60 |
61 | • **type**: [`PictureType`](../enums/PictureType.md)
62 |
63 | Gets and sets the type of the content visible in the picture stored in the current instance.
64 |
--------------------------------------------------------------------------------
/docs/interfaces/IRiffChunk.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IRiffChunk
2 |
3 | # Interface: IRiffChunk
4 |
5 | Interface for chunks that appear in a RIFF file.
6 |
7 | ## Implemented by
8 |
9 | - [`RiffList`](../classes/RiffList.md)
10 |
11 | ## Table of contents
12 |
13 | ### Properties
14 |
15 | - [chunkStart](IRiffChunk.md#chunkstart)
16 | - [fourcc](IRiffChunk.md#fourcc)
17 | - [originalDataSize](IRiffChunk.md#originaldatasize)
18 | - [originalTotalSize](IRiffChunk.md#originaltotalsize)
19 |
20 | ### Methods
21 |
22 | - [render](IRiffChunk.md#render)
23 |
24 | ## Properties
25 |
26 | ### chunkStart
27 |
28 | • **chunkStart**: `number`
29 |
30 | Offset into the file where the chunk begins. This is `undefined` if the object was
31 | constructed directly from data.
32 |
33 | ___
34 |
35 | ### fourcc
36 |
37 | • **fourcc**: `string`
38 |
39 | FOURCC code for the chunk.
40 |
41 | ___
42 |
43 | ### originalDataSize
44 |
45 | • **originalDataSize**: `number`
46 |
47 | Size of just the data contained within the current instance. Does not include the header or
48 | padding byte. This value does not update if contents of the chunk changes.
49 |
50 | ___
51 |
52 | ### originalTotalSize
53 |
54 | • **originalTotalSize**: `number`
55 |
56 | Original size of the chunk, including header and padding byte. This value does not update if
57 | the contents of the chunk changes.
58 |
59 | ## Methods
60 |
61 | ### render
62 |
63 | ▸ **render**(): [`ByteVector`](../classes/ByteVector.md)
64 |
65 | Renders the chunk, including the header and padding byte.
66 |
67 | #### Returns
68 |
69 | [`ByteVector`](../classes/ByteVector.md)
70 |
--------------------------------------------------------------------------------
/docs/interfaces/ISandwichFile.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / ISandwichFile
2 |
3 | # Interface: ISandwichFile
4 |
5 | Interface for a sandwich file.
6 |
7 | ## Implemented by
8 |
9 | - [`FlacFile`](../classes/FlacFile.md)
10 | - [`SandwichFile`](../classes/SandwichFile.md)
11 |
12 | ## Table of contents
13 |
14 | ### Properties
15 |
16 | - [mediaEndPosition](ISandwichFile.md#mediaendposition)
17 | - [mediaStartPosition](ISandwichFile.md#mediastartposition)
18 |
19 | ## Properties
20 |
21 | ### mediaEndPosition
22 |
23 | • `Readonly` **mediaEndPosition**: `number`
24 |
25 | Gets the position at which the media content of this file ends.
26 |
27 | ___
28 |
29 | ### mediaStartPosition
30 |
31 | • `Readonly` **mediaStartPosition**: `number`
32 |
33 | Gets the position at which the media content of this file starts.
34 |
--------------------------------------------------------------------------------
/docs/interfaces/IVideoCodec.md:
--------------------------------------------------------------------------------
1 | [node-taglib-sharp](../README.md) / [Exports](../modules.md) / IVideoCodec
2 |
3 | # Interface: IVideoCodec
4 |
5 | Interface that inherits the common codec information and adds video-specific information.
6 | When dealing with an [ICodec](ICodec.md), if [mediaTypes](ICodec.md#mediatypes) contains
7 | [Video](../enums/MediaTypes.md#video), it is safe to assume that the object also inherits [IVideoCodec](IVideoCodec.md)
8 | and can be recast without issue.
9 |
10 | ## Hierarchy
11 |
12 | - [`ICodec`](ICodec.md)
13 |
14 | ↳ **`IVideoCodec`**
15 |
16 | ## Implemented by
17 |
18 | - [`Mpeg4IsoVisualSampleEntry`](../classes/Mpeg4IsoVisualSampleEntry.md)
19 | - [`MpegVideoHeader`](../classes/MpegVideoHeader.md)
20 | - [`OggTheoraCodec`](../classes/OggTheoraCodec.md)
21 | - [`Properties`](../classes/Properties.md)
22 | - [`RiffBitmapInfoHeader`](../classes/RiffBitmapInfoHeader.md)
23 |
24 | ## Table of contents
25 |
26 | ### Properties
27 |
28 | - [description](IVideoCodec.md#description)
29 | - [durationMilliseconds](IVideoCodec.md#durationmilliseconds)
30 | - [mediaTypes](IVideoCodec.md#mediatypes)
31 | - [videoHeight](IVideoCodec.md#videoheight)
32 | - [videoWidth](IVideoCodec.md#videowidth)
33 |
34 | ## Properties
35 |
36 | ### description
37 |
38 | • **description**: `string`
39 |
40 | Gets a text description of the media represented by the current instance.
41 |
42 | #### Inherited from
43 |
44 | [ICodec](ICodec.md).[description](ICodec.md#description)
45 |
46 | ___
47 |
48 | ### durationMilliseconds
49 |
50 | • **durationMilliseconds**: `number`
51 |
52 | Duration of the media in milliseconds represented by the current instance.
53 |
54 | **`TODO`**
55 |
56 | Ensure milliseconds is the right way to interpret this field
57 |
58 | #### Inherited from
59 |
60 | [ICodec](ICodec.md).[durationMilliseconds](ICodec.md#durationmilliseconds)
61 |
62 | ___
63 |
64 | ### mediaTypes
65 |
66 | • **mediaTypes**: [`MediaTypes`](../enums/MediaTypes.md)
67 |
68 | Types of media represented by the current instance, bitwise combined.
69 |
70 | #### Inherited from
71 |
72 | [ICodec](ICodec.md).[mediaTypes](ICodec.md#mediatypes)
73 |
74 | ___
75 |
76 | ### videoHeight
77 |
78 | • **videoHeight**: `number`
79 |
80 | Height of the video in pixels represented by the current instance.
81 |
82 | ___
83 |
84 | ### videoWidth
85 |
86 | • **videoWidth**: `number`
87 |
88 | Width of the video in pixels represented by the current instance.
89 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-taglib-sharp",
3 | "description": "Read and write audio/video/picture tags using a similar interface to TagLib#",
4 | "version": "6.0.1",
5 | "license": "LGPL-2.1-or-later",
6 | "author": "Ben Russell (https://github.com/benrr101)",
7 | "repository": "github:benrr101/node-taglib-sharp",
8 | "bugs": "https://github.com/benrr101/node-taglib-sharp/issues",
9 | "main": "dist/index.js",
10 | "types": "dist/index.d.ts",
11 | "scripts": {
12 | "build": "tsc -p ./",
13 | "generate-docs": "typedoc --tsconfig tsconfig.json",
14 | "lint": "eslint -c .eslintrc.js --ext .ts ./src",
15 | "madge": "node node_modules/madge/bin/cli.js --warning --circular --extensions ts ./",
16 | "publish-coverage": "nyc report --reporter=text-lcov | coveralls",
17 | "test-unit": "mocha test-unit --ui bdd",
18 | "test-integration": "mocha test-integration --ui bdd",
19 | "test-unit-with-coverage": "nyc mocha test-unit --ui bdd"
20 | },
21 | "engines": {
22 | "node": ">=12.16.1"
23 | },
24 | "dependencies": {
25 | "iconv-lite": "^0.6.3",
26 | "os-locale": "^6.0.2",
27 | "uuid": "^8.3.2"
28 | },
29 | "devDependencies": {
30 | "@istanbuljs/nyc-config-typescript": "^1.0.2",
31 | "@testdeck/mocha": "^0.3.3",
32 | "@types/chai": "^4.3.0",
33 | "@types/chai-as-promised": "^7.1.0",
34 | "@types/stream-buffers": "^3.0.2",
35 | "@types/uuid": "^8.3.4",
36 | "@typescript-eslint/eslint-plugin": "^5.15.0",
37 | "@typescript-eslint/parser": "^5.15.0",
38 | "chai": "^4.3.6",
39 | "chai-as-promised": "^7.1.1",
40 | "coveralls": "^3.1.1",
41 | "eslint": "^8.57.1",
42 | "eslint-plugin-import": "^2.25.4",
43 | "eslint-plugin-jsdoc": "^38.0.4",
44 | "eslint-plugin-prefer-arrow": "^1.2.3",
45 | "madge": "^4.0.1",
46 | "mocha": "^10.2.0",
47 | "nyc": "^15.1.0",
48 | "source-map-support": "^0.5.16",
49 | "stream-buffers": "^3.0.2",
50 | "ts-node": "^10.7.0",
51 | "typedoc": "github:benrr101/typedoc#dont-copy-remarks",
52 | "typedoc-plugin-markdown": "^3.14.0",
53 | "typemoq": "^2.1.0",
54 | "typescript": "^4.5.5"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/aac/aacFile.ts:
--------------------------------------------------------------------------------
1 | import AacAudioHeader from "./aacAudioHeader";
2 | import AacFileSettings from "./aacFileSettings";
3 | import SandwichFile from "../sandwich/sandwichFile";
4 | import {CorruptFileError} from "../errors";
5 | import {File, ReadStyle} from "../file";
6 | import {IFileAbstraction} from "../fileAbstraction";
7 | import {Properties} from "../properties";
8 | import {TagTypes} from "../tag";
9 | import {NumberUtils} from "../utils";
10 |
11 | /**
12 | * This class extends {@link File} to provide tagging and properties for ADTS AAC audio files.
13 | */
14 | export default class AacFile extends SandwichFile {
15 | private static readonly DEFAULT_TAG_LOCATION_MAPPING = new Map boolean>([
16 | [TagTypes.Ape, () => AacFileSettings.preferApeTagAtFileEnd],
17 | [TagTypes.Id3v1, () => true],
18 | [TagTypes.Id3v2, () => AacFileSettings.preferId3v2TagAtFileEnd]
19 | ]);
20 |
21 | /** @inheritDoc */
22 | public constructor(file: IFileAbstraction|string, propertiesStyle: ReadStyle) {
23 | super(file, propertiesStyle, AacFile.DEFAULT_TAG_LOCATION_MAPPING, AacFileSettings.defaultTagTypes);
24 | }
25 |
26 | protected readProperties(readStyle: ReadStyle): Properties {
27 | // Skip if we're not reading the properties
28 | if (!NumberUtils.hasFlag(readStyle, ReadStyle.Average)) {
29 | return undefined;
30 | }
31 |
32 | // Only search the first 16k before giving up
33 | const firstHeader = AacAudioHeader.find(this, this.mediaStartPosition, 0x4000);
34 | if (!firstHeader) {
35 | throw new CorruptFileError("ADTS audio header not found");
36 | }
37 |
38 | firstHeader.streamLength = this.mediaEndPosition - this.mediaStartPosition;
39 | return new Properties(firstHeader.durationMilliseconds, [firstHeader]);
40 | }
41 | }
42 |
43 | // /////////////////////////////////////////////////////////////////////////
44 | // Register the file type
45 | [
46 | "taglib/aac",
47 | "audio/aac"
48 | ].forEach((mt) => File.addFileType(mt, AacFile));
49 |
--------------------------------------------------------------------------------
/src/aiff/aiffFileSettings.ts:
--------------------------------------------------------------------------------
1 | import {TagTypes} from "../tag";
2 | import {NumberUtils} from "../utils";
3 |
4 | /**
5 | * This class contains settings related to AIFF file operations. Open files will need to be re-read
6 | * in order for changes to take effect.
7 | */
8 | export default class AiffFileSettings {
9 | public static readonly SUPPORTED_TAG_TYPES = TagTypes.Id3v2;
10 |
11 | private static _defaultTagTypes = TagTypes.Id3v2;
12 |
13 | /**
14 | * Gets the default types of tags for an AIFF file. When opening a file, if these tag types do
15 | * not exist on the file, they will be created.
16 | */
17 | public static get defaultTagTypes(): TagTypes { return this._defaultTagTypes; }
18 | /**
19 | * Sets the default types of tags for an AIFF file. When opening a file, if these tag types do
20 | * not exist on the file, they will be created. See {@link SUPPORTED_TAG_TYPES} for a list of tag
21 | * types that are supported by node-taglib-sharp for AIFF files.
22 | */
23 | public static set defaultTagTypes(value: TagTypes) {
24 | const unsupportedTagTypes = NumberUtils.uintAnd(value, ~this.SUPPORTED_TAG_TYPES);
25 | if (unsupportedTagTypes !== 0) {
26 | throw new Error(
27 | `Argument error: node-taglib-sharp does not support tag types ${unsupportedTagTypes} for AIFF files`
28 | );
29 | }
30 |
31 | this._defaultTagTypes = value;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ape/apeFile.ts:
--------------------------------------------------------------------------------
1 | import ApeFileSettings from "./apeFileSettings";
2 | import SandwichFile from "../sandwich/sandwichFile";
3 | import {ApeStreamHeader} from "./apeStreamHeader";
4 | import {File, ReadStyle} from "../file";
5 | import {IFileAbstraction} from "../fileAbstraction";
6 | import {Properties} from "../properties";
7 | import {TagTypes} from "../tag";
8 | import {NumberUtils} from "../utils";
9 |
10 | /**
11 | * Provides tagging and properties support for Monkey's Audio APE files.
12 | * Note, a {@link ApeTag} will be added automatically to any file that doesn't contain one. This
13 | * change does not affect the physical file until {@link File.save} is called and can be reversed
14 | * using the following method: `file.removeTags(file.tagTypes & ~file.tagTypesOnDisk);`
15 | */
16 | export default class ApeFile extends SandwichFile {
17 | private static readonly DEFAULT_TAG_LOCATION_MAPPING = new Map boolean>([
18 | [TagTypes.Ape, () => ApeFileSettings.preferApeTagAtFileEnd],
19 | [TagTypes.Id3v1, () => true],
20 | [TagTypes.Id3v2, () => ApeFileSettings.preferId3v2TagAtFileEnd]
21 | ]);
22 |
23 | /** @inheritDoc */
24 | public constructor(file: IFileAbstraction|string, propertiesStyle: ReadStyle) {
25 | super(file, propertiesStyle, ApeFile.DEFAULT_TAG_LOCATION_MAPPING, ApeFileSettings.defaultTagTypes);
26 | }
27 |
28 | /** @inheritDoc */
29 | protected readProperties(readStyle: ReadStyle): Properties {
30 | // Skip if we're not reading the properties
31 | if (!NumberUtils.hasFlag(readStyle, ReadStyle.Average)) {
32 | return undefined;
33 | }
34 |
35 | // Find the header and use it to generate the properties
36 | this.seek(this.mediaStartPosition);
37 | const headerBlock = this.readBlock(ApeStreamHeader.SIZE);
38 | const header = new ApeStreamHeader(headerBlock, this.mediaEndPosition - this.mediaStartPosition);
39 | return new Properties(header.durationMilliseconds, [header]);
40 | }
41 | }
42 |
43 | // /////////////////////////////////////////////////////////////////////////
44 | // Register the file type
45 | [
46 | "taglib/ape",
47 | "audio/x-ape",
48 | "audio/ape",
49 | "application/x-ape"
50 | ].forEach((mt) => File.addFileType(mt, ApeFile));
51 |
--------------------------------------------------------------------------------
/src/asf/objects/unknownObject.ts:
--------------------------------------------------------------------------------
1 | import BaseObject from "./baseObject";
2 | import {ByteVector} from "../../byteVector";
3 | import {ObjectType} from "../constants";
4 | import {File} from "../../file";
5 | import {Guards} from "../../utils";
6 |
7 | /**
8 | * This class provides a representation of an ASF object that is unknown to the library, which can
9 | * be read from and written to disk.
10 | */
11 | export default class UnknownObject extends BaseObject {
12 | private _data: ByteVector;
13 |
14 | private constructor() {
15 | super();
16 | }
17 |
18 | /**
19 | * Constructs and initializes a new instance by reading the contents from a specified file.
20 | * @param file File from which the contents of the new instance will be read
21 | * @param position Index into the file where the object begins
22 | */
23 | public static fromFile(file: File, position: number): UnknownObject {
24 | const instance = new UnknownObject();
25 | instance.initializeFromFile(file, position);
26 | instance._data = file.readBlock(instance.originalSize - 24).toByteVector();
27 | return instance;
28 | }
29 |
30 | // #region Properties
31 |
32 | /**
33 | * Gets the data contained in the current instance.
34 | */
35 | public get data(): ByteVector { return this._data; }
36 | /**
37 | * Sets the data contained in the current instance.
38 | * @param value Data to store in the current instance. Must be truthy.
39 | */
40 | public set data(value: ByteVector) {
41 | Guards.truthy(value, "value");
42 | this._data = value;
43 | }
44 |
45 | /** @inheritDoc */
46 | public get objectType(): ObjectType { return ObjectType.UnknownObject; }
47 |
48 | // #endregion
49 |
50 | /** @inheritDoc */
51 | public render(): ByteVector {
52 | return super.renderInternal(this._data);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/asf/readWriteUtils.ts:
--------------------------------------------------------------------------------
1 | import UuidWrapper from "../uuidWrapper";
2 | import {ByteVector, StringType} from "../byteVector";
3 | import {File} from "../file";
4 |
5 | /**
6 | * Utilities for reading and writing ASF data.
7 | * @internal
8 | */
9 | export default {
10 | /**
11 | * Reads a 4-byte double word from the current instance.
12 | * @param file File to read the double word from
13 | */
14 | readDWord: (file: File): number => {
15 | return file.readBlock(4).toUint(false);
16 | },
17 |
18 | /**
19 | * Reads a 16-byte GUID from the current instance.
20 | * @param file File to read the guid from
21 | */
22 | readGuid: (file: File): UuidWrapper => {
23 | return new UuidWrapper(file.readBlock(16));
24 | },
25 |
26 | /**
27 | * Reads an 8-byte quad word from the current instance.
28 | * @param file File to read the quad word from
29 | */
30 | readQWord: (file: File): bigint => {
31 | return file.readBlock(8).toLong(false);
32 | },
33 |
34 | /**
35 | * Reads a UTF-16LE string of specified length in bytes from the current instance. If null
36 | * byte is found before the end of specified end of the string, the string will be shortened
37 | * at the null byte.
38 | * @param length Length in bytes to read as the string
39 | * @param file File to read Unicode from
40 | */
41 | readUnicode: (file: File, length: number): string => {
42 | const string = file.readBlock(length).toString(StringType.UTF16LE);
43 | const nullIndex = string.indexOf("\0");
44 | return nullIndex >= 0 ? string.substring(0, nullIndex) : string;
45 | },
46 |
47 | /**
48 | * Reads a 2-byte word from the current instance.
49 | * @param file File to read the word from
50 | */
51 | readWord: (file: File): number => {
52 | return file.readBlock(2).toUshort(false);
53 | },
54 |
55 | /**
56 | * Renders a 4-byte double word.
57 | * @param value Double word to render
58 | */
59 | renderDWord: (value: number): ByteVector => {
60 | return ByteVector.fromUint(value, false);
61 | },
62 |
63 | /**
64 | * Renders an 8-byte quad word.
65 | * @param value Quad word to render
66 | */
67 | renderQWord: (value: bigint): ByteVector => {
68 | return ByteVector.fromUlong(value, false);
69 | },
70 |
71 | /**
72 | * Renders a unicode string.
73 | * @param value Text to render
74 | */
75 | renderUnicode: (value: string): ByteVector => {
76 | return ByteVector.concatenate(
77 | ByteVector.fromString(value, StringType.UTF16LE),
78 | ByteVector.fromUshort(0, false)
79 | );
80 | },
81 |
82 | /**
83 | * Renders a 2-byte word.
84 | * @param value Word to render
85 | */
86 | renderWord: (value: number): ByteVector => {
87 | return ByteVector.fromUshort(value, false);
88 | },
89 | };
90 |
--------------------------------------------------------------------------------
/src/ebml/ebmlParserOptions.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Class that stores the options used for parsing the current EBML element.
3 | */
4 | export default interface EbmlParserOptions {
5 | /**
6 | * Maximum permitted length in bytes of element IDs.
7 | */
8 | maxIdLength?: number;
9 |
10 | /**
11 | * Maximum permitted length in bytes of the expressions of all element data size.
12 | */
13 | maxSizeLength?: number;
14 | }
15 |
--------------------------------------------------------------------------------
/src/ebml/ids.ts:
--------------------------------------------------------------------------------
1 | export class EbmlIds {
2 | /**
3 | * Indicates an EBML Header element.
4 | */
5 | public static readonly EBML_HEADER = 0x1A45DFA3;
6 |
7 | /**
8 | * Indicates an EBML Version element.
9 | */
10 | public static readonly EBML_VERSION = 0x4286;
11 |
12 | /**
13 | * Indicates an EBML Read Version element.
14 | */
15 | public static readonly EBML_READ_VERSION = 0x42F7;
16 |
17 | /**
18 | * Indicates an EBML Max ID Length element.
19 | */
20 | public static readonly EBML_MAX_IDLENGTH = 0x42F2;
21 |
22 | /**
23 | * Indicates an EBML Max Size Length element.
24 | */
25 | public static readonly EBML_MAX_SIZE_LENGTH = 0x42F3;
26 |
27 | /**
28 | * Indicates an EBML Doc Type element.
29 | */
30 | public static readonly EBML_DOC_TYPE = 0x4282;
31 |
32 | /**
33 | * Indicates an EBML Doc Type Version element.
34 | */
35 | public static readonly EBML_DOC_TYPE_VERSION = 0x4287;
36 |
37 | /**
38 | * Indicates an EBML Doc Type Read Version element.
39 | */
40 | public static readonly EBML_DOC_TYPE_READ_VERSION = 0x4285;
41 |
42 | /**
43 | * Indicates an EBML Void element.
44 | */
45 | public static readonly EBML_VOID = 0xEC;
46 | }
47 |
--------------------------------------------------------------------------------
/src/errors.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Error class that indicates the file is likely corrupt.
3 | */
4 | export class CorruptFileError extends Error {
5 | public constructor(msg?: string) {
6 | super(msg);
7 | }
8 | }
9 |
10 | /**
11 | * Error class that indicates a piece of functionality is not implemented in the current version.
12 | */
13 | export class NotImplementedError extends Error {
14 | public constructor(message?: string) {
15 | super(`Not implemented${message ? `: ${message}` : ""}`);
16 | }
17 | }
18 |
19 | /**
20 | * Error class that indicates a feature or format is not supported in the current version.
21 | */
22 | export class NotSupportedError extends Error {
23 | public constructor(message?: string) {
24 | super(`Not supported${message ? `: ${message}` : ""}`);
25 | }
26 | }
27 |
28 | /**
29 | * Error class that indicates a format is not supported in the current version.
30 | */
31 | export class UnsupportedFormatError extends Error {
32 | public constructor(message?: string) {
33 | super(`Unsupported format${message ? `: ${message}` : ""}`);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/id3v2/id3v2ExtendedHeader.ts:
--------------------------------------------------------------------------------
1 | import SyncData from "./syncData";
2 | import {ByteVector} from "../byteVector";
3 | import {Guards} from "../utils";
4 |
5 | /**
6 | * This class is a filler until support for reading and writing the ID3v2 extended header is
7 | * implemented.
8 | */
9 | export default class Id3v2ExtendedHeader {
10 | private _size: number;
11 |
12 | private constructor() { /* private to enforce construction via static methods */ }
13 |
14 | /**
15 | * Constructs and initializes a new instance by reading the raw contents.
16 | * @param data Raw extended header structure
17 | * @param version ID3v2 version. Must be an unsigned 8-bit integer.
18 | */
19 | public static fromData(data: ByteVector, version: number): Id3v2ExtendedHeader {
20 | Guards.truthy(data, "data");
21 | Guards.byte(version, "version");
22 |
23 | const header = new Id3v2ExtendedHeader();
24 | header.parse(data, version);
25 | return header;
26 | }
27 |
28 | /**
29 | * Constructs and initializes a new instance with no contents.
30 | */
31 | public static fromEmpty(): Id3v2ExtendedHeader {
32 | return new Id3v2ExtendedHeader();
33 | }
34 |
35 | /**
36 | * Gets the size of the data on disk in bytes.
37 | */
38 | public get size(): number { return this._size; }
39 |
40 | private parse(data: ByteVector, version: number): void {
41 | this._size = (version === 3 ? 4 : 0)
42 | + SyncData.toUint(data.subarray(0, 4));
43 |
44 | // TODO: Are we going to actually support any of the flags?
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/interfaces.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Interface for objects that can (and should) be disposed after they are no longer needed.
3 | */
4 | export interface IDisposable {
5 | /**
6 | * Disposes the current instance.
7 | */
8 | dispose(): void;
9 | }
10 |
11 | /**
12 | * Interface for objects that can be lazily loaded.
13 | */
14 | export interface ILazy {
15 | /**
16 | * Gets whether the object has been loaded.
17 | */
18 | isLoaded: boolean;
19 |
20 | /**
21 | * Loads the object.
22 | */
23 | load(): void;
24 | }
25 |
--------------------------------------------------------------------------------
/src/matroska/matroskaTag.ts:
--------------------------------------------------------------------------------
1 | import MatroskaTagValue from "./matroskaTagValue";
2 | import {MatroskaTagTarget} from "./matroskaTagTarget";
3 | import {Guards} from "../utils";
4 |
5 | /**
6 | * Abstraction on that represents the combination of a Matroska simple tag and a tag target.
7 | * @remarks
8 | * This is different from the tag concept in Matroska. This is a 1:1 relation between
9 | * target and value while Matroska tags are 1:many relationship of target to tag. Therefore,
10 | * the target must be cloned when constructing >1 tag with the same target.
11 | */
12 | export default class MatroskaTag {
13 | private readonly _value: MatroskaTagValue;
14 | private readonly _target: MatroskaTagTarget;
15 |
16 | /**
17 | * Constructs and initializes a new instance using a simple tag and a target.
18 | * @param value Tag value to store in the instance
19 | * @param target Tag target that the tag instance applies to
20 | */
21 | public constructor(value: MatroskaTagValue, target: MatroskaTagTarget) {
22 | Guards.truthy(value, "value");
23 | Guards.truthy(target, "target");
24 |
25 | this._value = value;
26 | this._target = target;
27 | }
28 |
29 | /**
30 | * Target that the tag value applies to
31 | */
32 | public get target(): MatroskaTagTarget { return this._target; }
33 |
34 | /**
35 | * Value of the tag
36 | */
37 | public get value(): MatroskaTagValue { return this._value; }
38 | }
39 |
--------------------------------------------------------------------------------
/src/matroska/tracks/audioTrack.ts:
--------------------------------------------------------------------------------
1 | import EbmlElement from "../../ebml/ebmlElement";
2 | import {MatroskaIds} from "../matroskaIds";
3 | import {ILosslessAudioCodec, MediaTypes} from "../../properties";
4 | import {MatroskaTrackType, Track} from "./track";
5 | import {Guards} from "../../utils";
6 |
7 | export default class AudioTrack extends Track implements ILosslessAudioCodec {
8 | private readonly _bitDepth: number;
9 | private readonly _channels: number;
10 | private readonly _sampleRate: number;
11 |
12 | public constructor(trackElements: Map, audioElements: Map) {
13 | super(trackElements);
14 |
15 | Guards.truthy(audioElements, "audioElements");
16 | if (this.type !== MatroskaTrackType.Audio) {
17 | throw new Error(`Video track constructor used to construct type ${this.type} track.`);
18 | }
19 |
20 | // Read the relevant values
21 | this._channels = audioElements.get(MatroskaIds.CHANNELS)?.getSafeUint();
22 | this._bitDepth = audioElements.get(MatroskaIds.BIT_DEPTH)?.getSafeUint();
23 | this._sampleRate = audioElements.get(MatroskaIds.SAMPLING_FREQ)?.getDouble();
24 | }
25 |
26 | /** @inheritDoc */
27 | public get audioBitrate(): number {
28 | // @TODO How can we calculate that
29 | return undefined;
30 | }
31 |
32 | /** @inheritDoc */
33 | public get audioChannels(): number { return this._channels; }
34 |
35 | /** @inheritDoc */
36 | public get audioSampleRate(): number { return this._sampleRate; }
37 |
38 | /** @inheritDoc */
39 | public get bitsPerSample(): number { return this._bitDepth; }
40 |
41 | /** @inheritDoc */
42 | public get mediaTypes(): MediaTypes {
43 | // @TODO: Determine if the codec is lossless or not
44 | return MediaTypes.Audio;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/matroska/tracks/trackFactory.ts:
--------------------------------------------------------------------------------
1 | import AudioTrack from "./audioTrack";
2 | import EbmlElement from "../../ebml/ebmlElement";
3 | import EbmlParser from "../../ebml/ebmlParser";
4 | import {MatroskaIds} from "../matroskaIds";
5 | import {MatroskaTrackType, Track} from "./track";
6 | import {VideoTrack} from "./videoTrack";
7 |
8 | export default class TrackFactory {
9 | public static fromTrackElement(trackElement: EbmlElement): Track {
10 | // Read all the elements from the track
11 | const elements = EbmlParser.getAllElements(trackElement.getParser());
12 |
13 | // Parse the elements into a track object
14 | switch (elements.get(MatroskaIds.TRACK_TYPE)?.getSafeUint()) {
15 | case MatroskaTrackType.Audio:
16 | const audioElementParser = elements.get(MatroskaIds.AUDIO).getParser();
17 | const audioElements = EbmlParser.getAllElements(audioElementParser);
18 | return new AudioTrack(elements, audioElements);
19 | case MatroskaTrackType.Video:
20 | const videoElementParser = elements.get(MatroskaIds.VIDEO).getParser();
21 | const videoElements = EbmlParser.getAllElements(videoElementParser);
22 | return new VideoTrack(elements, videoElements);
23 | default:
24 | return new Track(elements);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/mpeg/mpegAudioFile.ts:
--------------------------------------------------------------------------------
1 | import MpegAudioFileSettings from "./mpegAudioFileSettings";
2 | import MpegAudioHeader from "./mpegAudioHeader";
3 | import SandwichFile from "../sandwich/sandwichFile";
4 | import {CorruptFileError} from "../errors";
5 | import {File, ReadStyle} from "../file";
6 | import {IFileAbstraction} from "../fileAbstraction";
7 | import {Properties} from "../properties";
8 | import {TagTypes} from "../tag";
9 | import {NumberUtils} from "../utils";
10 |
11 | /**
12 | * This class extends {@link SandwichFile} to provide tagging and properties support for
13 | * MPEG-1, MPEG-2, and MPEG-2.5 non-containerized audio files.
14 | */
15 | export default class MpegAudioFile extends SandwichFile {
16 | private static readonly DEFAULT_TAG_LOCATION_MAPPING = new Map boolean>([
17 | [TagTypes.Ape, () => MpegAudioFileSettings.preferApeTagAtFileEnd],
18 | [TagTypes.Id3v1, () => true],
19 | [TagTypes.Id3v2, () => MpegAudioFileSettings.preferId3v2TagAtFileEnd]
20 | ]);
21 |
22 | private _firstHeader: MpegAudioHeader;
23 |
24 | public constructor(file: IFileAbstraction|string, propertiesStyle: ReadStyle) {
25 | super(file, propertiesStyle, MpegAudioFile.DEFAULT_TAG_LOCATION_MAPPING, MpegAudioFileSettings.defaultTagTypes);
26 | }
27 |
28 | protected readProperties(readStyle: ReadStyle): Properties {
29 | if (!NumberUtils.hasFlag(readStyle, ReadStyle.Average)) {
30 | return undefined;
31 | }
32 |
33 | // @TODO: if readStyle is higher than average, scan the entire file to accurately calculate
34 | // the duration and bitrate
35 |
36 | const searchStart = this.mediaStartPosition;
37 | const searchEnd = searchStart + 0x400;
38 | const streamLength = this.mediaEndPosition - this.mediaStartPosition;
39 |
40 | this._firstHeader = MpegAudioHeader.fromFile(this, searchStart, searchEnd, streamLength);
41 | if (!this._firstHeader) {
42 | throw new CorruptFileError("MPEG audio header not found");
43 | }
44 |
45 | return new Properties(this._firstHeader.durationMilliseconds, [this._firstHeader]);
46 | }
47 | }
48 |
49 | // /////////////////////////////////////////////////////////////////////////
50 | // Register the file type
51 | [
52 | "taglib/mp3",
53 | "audio/x-mp3",
54 | "application/x-id3",
55 | "audio/mpeg",
56 | "audio/x-mpeg",
57 | "audio/x-mpeg-3",
58 | "audio/mpeg3",
59 | "audio/mp3",
60 | "taglib/m2a",
61 | "taglib/mp2",
62 | "taglib/mp1",
63 | "audio/x-mp2",
64 | "audio/x-mp1"
65 | ].forEach((mt) => File.addFileType(mt, MpegAudioFile));
66 |
--------------------------------------------------------------------------------
/src/mpeg/mpegContainerFileSettings.ts:
--------------------------------------------------------------------------------
1 | import {TagTypes} from "../tag";
2 | import {NumberUtils} from "../utils";
3 |
4 | /**
5 | * This class contains settings related to MPEG container file operations. Open files will need to
6 | * be re-read in order for changes to take effect.
7 | */
8 | export default class MpegContainerFileSettings {
9 | public static readonly SUPPORTED_TAG_TYPES = TagTypes.Id3v1 | TagTypes.Id3v2 | TagTypes.Ape;
10 |
11 | private static _defaultTagTypes = TagTypes.Id3v1 | TagTypes.Id3v2;
12 |
13 | /**
14 | * Gets the default types of tags for an MPEG container file. When opening a file, if these tag
15 | * types do not exist on the file, they will be created.
16 | */
17 | public static get defaultTagTypes(): TagTypes { return this._defaultTagTypes; }
18 | /**
19 | * Sets the default types of tags for an MPEG container file. When opening a file, if these tag
20 | * types do not exist on the file, they will be created. See {@link SUPPORTED_TAG_TYPES} for a
21 | * list of tag types that are supported by node-taglib-sharp for MPEG container files.
22 | */
23 | public static set defaultTagTypes(value: TagTypes) {
24 | const unsupportedTagTypes = NumberUtils.uintAnd(value, ~this.SUPPORTED_TAG_TYPES);
25 | if (unsupportedTagTypes !== 0) {
26 | throw new Error(
27 | `Argument error: node-taglib-sharp does not support tag types ${unsupportedTagTypes} for AAC files`
28 | );
29 | }
30 |
31 | this._defaultTagTypes = value;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/mpeg/mpegEnums.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Indicates the MPEG audio channel mode of a file or stream.
3 | */
4 | export enum ChannelMode {
5 | /** Stereo */
6 | Stereo = 0,
7 |
8 | /** Joint Stereo */
9 | JointStereo = 1,
10 |
11 | /** Dual Channel Mono */
12 | DualChannel = 2,
13 |
14 | /** Single Channel Mono */
15 | SingleChannel= 3
16 | }
17 |
18 | /**
19 | * Indicates the MPEG version of a file or stream.
20 | */
21 | export enum MpegVersion {
22 | /** Unknown version */
23 | Unknown = -1,
24 |
25 | /** MPEG-1 */
26 | Version1 = 0,
27 |
28 | /** MPEG-2 */
29 | Version2 = 1,
30 |
31 | /** MPEG-2.5 */
32 | Version25 = 2
33 | }
34 |
--------------------------------------------------------------------------------
/src/mpeg/mpegVideoHeader.ts:
--------------------------------------------------------------------------------
1 | import {CorruptFileError} from "../errors";
2 | import {File} from "../file";
3 | import {IVideoCodec, MediaTypes} from "../properties";
4 | import {Guards, NumberUtils} from "../utils";
5 |
6 | /**
7 | * Provides information about an MPEG video stream.
8 | */
9 | export default class MpegVideoHeader implements IVideoCodec {
10 | private static readonly FRAME_RATES = [
11 | 0, 24000 / 1001, 24, 25, 30000 / 1001, 30, 50, 60000 / 1001, 60
12 | ];
13 |
14 | private readonly _frameRateIndex: number;
15 | private readonly _videoBitrate: number;
16 | private readonly _videoHeight: number;
17 | private readonly _videoWidth: number;
18 |
19 | /**
20 | * Constructs and initializes a new instance of {@link MpegVideoHeader} by reading it from a
21 | * specified location in a specified file.
22 | * @param file File to read the header from
23 | * @param position Position in `file` at which the header begins
24 | */
25 | public constructor(file: File, position: number) {
26 | Guards.truthy(file, "file");
27 | Guards.safeUint(position, "position");
28 |
29 | file.seek(position);
30 | const data = file.readBlock(7);
31 |
32 | if (data.length < 7) {
33 | throw new CorruptFileError("Insufficient data in header");
34 | }
35 |
36 | this._videoWidth = data.subarray(0, 2).toUshort() >>> 4;
37 | this._videoHeight = NumberUtils.uintAnd(data.subarray(1, 2).toUshort(), 0x0FFF);
38 | this._frameRateIndex = NumberUtils.uintAnd(data.get(3), 0x0F);
39 | this._videoBitrate = NumberUtils.uintAnd(NumberUtils.uintRShift(data.subarray(4, 3).toUint(), 6), 0x3FFFF);
40 | }
41 |
42 | // #region
43 |
44 | /** @inheritDoc */
45 | public get description(): string { return "MPEG Video"; }
46 |
47 | /**
48 | * @inheritDoc
49 | * @remarks For MPEG, this is always 0
50 | */
51 | // @TODO: Can we calculate the duration?
52 | public get durationMilliseconds(): number { return 0; }
53 |
54 | /** @inheritDoc */
55 | public get mediaTypes(): MediaTypes { return MediaTypes.Video; }
56 |
57 | /** @inheritDoc */
58 | public get videoBitrate(): number { return this._videoBitrate; }
59 |
60 | /** @inheritDoc */
61 | public get videoFrameRate(): number {
62 | return this._frameRateIndex < 9 ? MpegVideoHeader.FRAME_RATES[this._frameRateIndex] : 0;
63 | }
64 |
65 | /** @inheritDoc */
66 | public get videoHeight(): number { return this._videoHeight; }
67 |
68 | /** @inheritDoc */
69 | public get videoWidth(): number { return this._videoWidth; }
70 |
71 | // #endregion
72 | }
73 |
--------------------------------------------------------------------------------
/src/mpeg/vbrHeader.ts:
--------------------------------------------------------------------------------
1 | export default abstract class VbrHeader {
2 | private readonly _bitrateKilobytes: number | undefined;
3 | private readonly _durationMilliseconds: number | undefined;
4 | private readonly _totalFrames: number | undefined;
5 | private readonly _totalBytes: number | undefined;
6 |
7 | protected constructor(
8 | totalFrames?: number,
9 | totalBytes?: number,
10 | durationSeconds?: number,
11 | bitrateBytes?: number
12 | ) {
13 | this._totalFrames = totalFrames;
14 | this._totalBytes = totalBytes;
15 | this._durationMilliseconds = durationSeconds ? durationSeconds * 1000 : undefined;
16 | this._bitrateKilobytes = bitrateBytes ? Math.floor(bitrateBytes / 1000) : undefined;
17 | }
18 |
19 | /**
20 | * Gets the bitrate of the ile in kilobytes per second, if it could be calculated using the
21 | * current instance. `undefined`, otherwise.
22 | */
23 | public get bitrateKilobytes(): number | undefined { return this._bitrateKilobytes; }
24 |
25 | /**
26 | * Gets the duration of the file in milliseconds, if it could be calculated using the current
27 | * instance. `undefined`, otherwise.
28 | */
29 | public get durationMilliseconds(): number | undefined { return this._durationMilliseconds; }
30 |
31 | /**
32 | * Gets the total number of frames in the file, as indicated by the current instance.
33 | */
34 | public get totalFrames(): number | undefined { return this._totalFrames; }
35 |
36 | /**
37 | * Gets the total size of the file in bytes, as indicated by the current instance.
38 | */
39 | public get totalBytes(): number | undefined { return this._totalBytes;}
40 | }
--------------------------------------------------------------------------------
/src/mpeg/vbriHeader.ts:
--------------------------------------------------------------------------------
1 | import VbrHeader from "./vbrHeader";
2 | import {ByteVector, StringType} from "../byteVector";
3 | import {File} from "../file";
4 | import {Guards} from "../utils";
5 |
6 | /**
7 | * Information about a variable bitrate MPEG audio stream encoded by the Fraunhofer encoder
8 | */
9 | export default class VbriHeader extends VbrHeader {
10 | private static readonly FILE_IDENTIFIER = ByteVector.fromString("VBRI", StringType.Latin1).makeReadOnly();
11 | private static readonly HEADER_OFFSET = 36;
12 |
13 | private constructor(totalFrames: number, totalBytes: number, durationSeconds: number, bitrateBytes: number) {
14 | super(totalFrames, totalBytes, durationSeconds, bitrateBytes);
15 | }
16 |
17 | public static fromFile(
18 | file: File,
19 | mpegHeaderPosition: number,
20 | samplesPerFrame: number,
21 | samplesPerSecond: number
22 | ): VbriHeader {
23 | Guards.truthy(file, "files");
24 | Guards.safeUint(mpegHeaderPosition, "mpegHeaderPosition");
25 | Guards.uint(samplesPerFrame, "samplesPerFrame");
26 | Guards.greaterThanInclusive(samplesPerFrame, 1, "samplesPerFrame");
27 | Guards.uint(samplesPerSecond, "samplesPerSecond");
28 | Guards.greaterThanInclusive(samplesPerSecond, 1, "samplesPerSecond");
29 |
30 | // Seek to the position in the file where the VBRI header should be and read it
31 | file.seek(mpegHeaderPosition + this.HEADER_OFFSET);
32 |
33 | const vbriData = file.readBlock(24);
34 | if (vbriData.length !== 24 || !vbriData.startsWith(this.FILE_IDENTIFIER)) {
35 | return undefined;
36 | }
37 |
38 | // Parse the header
39 | const delay = vbriData.subarray(6, 2).toUshort();
40 | const totalBytes = vbriData.subarray(10, 4).toUint();
41 | const totalFrames = vbriData.subarray(14, 4).toUint();
42 |
43 | // Calculate the rest of the values
44 | const totalSamples = (totalFrames * samplesPerFrame);
45 | const bitrateBytes = (totalBytes * 8) / (totalSamples / samplesPerSecond);
46 | const durationSeconds = (totalSamples - delay) / samplesPerSecond;
47 |
48 | return new VbriHeader(totalFrames, totalBytes, durationSeconds, bitrateBytes);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/mpeg4/boxes/appleAdditionalInfoBox.ts:
--------------------------------------------------------------------------------
1 | import FullBox from "./fullBox";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector, StringType} from "../../byteVector";
4 | import {File} from "../../file";
5 | import {Guards, StringUtils} from "../../utils";
6 |
7 | /**
8 | * This class extends {@link FullBox} to provide an implementation of an Apple AdditionalInfoBox.
9 | */
10 | export default class AppleAdditionalInfoBox extends FullBox {
11 | /**
12 | * Private constructor to force construction via static functions.
13 | */
14 | private constructor() {
15 | super();
16 | }
17 |
18 | /**
19 | * Constructs and initializes a new instance of {@link AppleAdditionalInfoBox} with a provided header
20 | * and handler by reading the contents from a specified file.
21 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
22 | * @param file A {@link File} object to read the contents of the box from.
23 | * @param handlerType Type of the handler box object containing the handler that applies to the
24 | * new instance, or undefined if no handler applies.
25 | */
26 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): AppleAdditionalInfoBox {
27 | const instance = new AppleAdditionalInfoBox();
28 | instance.initializeFromHeaderFileAndHandler(header, file, handlerType);
29 | instance.data = file.readBlock(instance.dataSize > 0 ? instance.dataSize : 0);
30 |
31 | return instance;
32 | }
33 |
34 | /**
35 | * Constructs and initializes a new instance of {@link FullBox} with a provided header, version, and flags.
36 | * @param type A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
37 | * @param version A value containing the version of the new instance.
38 | * @param flags A value containing the flags for the new instance.
39 | */
40 | public static fromTypeVersionAndFlags(type: ByteVector, version: number, flags: number): AppleAdditionalInfoBox {
41 | const instance = new AppleAdditionalInfoBox();
42 | instance.initializeFromTypeVersionAndFlags(type, version, flags);
43 |
44 | return instance;
45 | }
46 |
47 | /**
48 | * Gets the text contained in the current instance.
49 | */
50 | public get text(): string { return StringUtils.trimStart(this.data.toString(StringType.Latin1), "\0"); }
51 | /**
52 | * Sets the text contained in the current instance.
53 | */
54 | public set text(v: string) {
55 | Guards.notNullOrUndefined(v, "v");
56 | this.data = ByteVector.fromString(v, StringType.Latin1);
57 | }
58 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/appleAnnotationBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector} from "../../byteVector";
4 |
5 | /**
6 | * This class extends {@link Mpeg4Box} to provide an implementation of an Apple AnnotationBox.
7 | */
8 | export default class AppleAnnotationBox extends Mpeg4Box {
9 | /**
10 | * Private constructor to force construction via static functions.
11 | */
12 | private constructor() {
13 | super();
14 | }
15 |
16 | /**
17 | * Constructs and initializes a new instance of {@link AppleAnnotationBox} with a provided header and
18 | * handler by reading the contents from a specified file.
19 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
20 | * @param handlerType Type of the handler box object containing the handler that applies to the
21 | * new instance, or undefined if no handler applies.
22 | */
23 | public static fromHeader(header: Mpeg4BoxHeader, handlerType: ByteVector): AppleAnnotationBox {
24 | const instance = new AppleAnnotationBox();
25 | instance.initializeFromHeader(header, handlerType);
26 |
27 | return instance;
28 | }
29 |
30 | /**
31 | * Constructs and initializes a new instance of {@link AppleAnnotationBox} of specified type with no children.
32 | * @param type A {@link ByteVector} object containing a 4-byte box type.
33 | */
34 | public static fromType(type: ByteVector): AppleAnnotationBox {
35 | const instance = new AppleAnnotationBox();
36 | instance.initializeFromType(type);
37 |
38 | return instance;
39 | }
40 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoFreeSpaceBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import Mpeg4BoxType from "../mpeg4BoxType";
4 | import {ByteVector} from "../../byteVector";
5 | import {Guards} from "../../utils";
6 |
7 | /**
8 | * This class extends {@link Mpeg4Box} to provide an implementation of a ISO/IEC 14496-12 FreeSpaceBox.
9 | */
10 | export default class IsoFreeSpaceBox extends Mpeg4Box {
11 | private _padding: number;
12 |
13 | /**
14 | * Private constructor to force construction via static functions.
15 | */
16 | private constructor() {
17 | super();
18 | }
19 |
20 | /**
21 | * Constructs and initializes a new instance of {@link IsoFreeSpaceBox} with a provided header and
22 | * handler by reading the contents from a specified file.
23 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
24 | * @param handlerType Type of the handler box object containing the handler that applies to the
25 | * new instance, or undefined if no handler applies.
26 | */
27 | public static fromHeader(header: Mpeg4BoxHeader, handlerType: ByteVector): IsoFreeSpaceBox {
28 | const instance = new IsoFreeSpaceBox();
29 | instance.initializeFromHeader(header, handlerType);
30 | instance._padding = instance.dataSize;
31 |
32 | return instance;
33 | }
34 |
35 | /**
36 | * Constructs and initializes a new instance of {@link IsoFreeSpaceBox} to occupy a specified number of bytes.
37 | * @param padding A value specifying the number of bytes the new instance should occupy when rendered.
38 | */
39 | public static fromPadding(padding: number): IsoFreeSpaceBox {
40 | const instance = new IsoFreeSpaceBox();
41 | instance.initializeFromType(Mpeg4BoxType.FREE);
42 | instance.paddingSize = padding;
43 |
44 | return instance;
45 | }
46 |
47 | /**
48 | * Gets the data contained in the current instance.
49 | */
50 | public get data(): ByteVector { return ByteVector.fromSize(this._padding); }
51 | /**
52 | * Sets the data contained in the current instance.
53 | */
54 | public set data(v: ByteVector) { this._padding = v ? v.length : 0; }
55 |
56 | /**
57 | * Gets the size the current instance will occupy when rendered.
58 | * @returns A value containing the size the current instance will occupy when rendered.
59 | */
60 | public get paddingSize(): number { return this._padding + 8; }
61 | /**
62 | * Sets the size the current instance will occupy when rendered.
63 | */
64 | public set paddingSize(v: number) {
65 | Guards.safeUint(v, "v");
66 | this._padding = v - 8;
67 | }
68 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoMetaBox.ts:
--------------------------------------------------------------------------------
1 | import FullBox from "./fullBox";
2 | import IsoHandlerBox from "./isoHandlerBox";
3 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
4 | import Mpeg4BoxType from "../mpeg4BoxType";
5 | import {ByteVector} from "../../byteVector";
6 | import {File} from "../../file";
7 | import {Guards} from "../../utils";
8 |
9 | /**
10 | * This class extends {@link FullBox} to provide an implementation of a ISO/IEC 14496-12 MetaBox.
11 | */
12 | export default class IsoMetaBox extends FullBox {
13 | /**
14 | * Private constructor to force construction via static functions.
15 | */
16 | private constructor() {
17 | super();
18 | }
19 |
20 | /**
21 | * Constructs and initializes a new instance of {@link IsoMetaBox} with a provided header and
22 | * handler by reading the contents from a specified file.
23 | * @param file A {@link File} object to read the contents of the box from.
24 | * new instance, or undefined if no handler applies.
25 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
26 | * @param handlerType Type of the handler box object containing the handler that applies to the
27 | */
28 | public static fromFile(file: File, header: Mpeg4BoxHeader, handlerType: ByteVector): IsoMetaBox {
29 | const instance = new IsoMetaBox();
30 | instance.initializeFromHeaderFileAndHandler(header, file, handlerType);
31 |
32 | return instance;
33 | }
34 |
35 | /**
36 | * Constructs and initializes a new instance of {@link IsoMetaBox} with a specified handler.
37 | * @param handlerType A {@link ByteVector} object specifying a 4 byte handler type.
38 | * @param handlerName A `string` object specifying the handler name.
39 | */
40 | public static fromHandler(handlerType: ByteVector, handlerName?: string): IsoMetaBox {
41 | Guards.truthy(handlerType, "handlerType");
42 | if (handlerType.length < 4) {
43 | throw new Error("The handler type must be four bytes long.");
44 | }
45 |
46 | const instance = new IsoMetaBox();
47 | instance.initializeFromTypeVersionAndFlags(Mpeg4BoxType.META, 0, 0);
48 |
49 | const handlerBox = IsoHandlerBox.fromHandlerTypeAndHandlerName(handlerType, handlerName);
50 | instance.addChild(handlerBox);
51 |
52 | return instance;
53 | }
54 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoSampleDescriptionBox.ts:
--------------------------------------------------------------------------------
1 | import FullBox from "./fullBox";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {File} from "../../file";
4 | import {ByteVector} from "../../byteVector";
5 |
6 | /**
7 | * This class extends {@link FullBox} to provide an implementation of a ISO/IEC 14496-12 SampleDescriptionBox.
8 | */
9 | export default class IsoSampleDescriptionBox extends FullBox {
10 | private _entryCount: number;
11 |
12 | /**
13 | * Private constructor to force construction via static functions.
14 | */
15 | private constructor() {
16 | super();
17 | }
18 |
19 | /**
20 | * Constructs and initializes a new instance of {@link IsoSampleDescriptionBox} with a provided header
21 | * and handler by reading the contents from a specified file.
22 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
23 | * @param file A {@link File} object to read the contents of the box from.
24 | * @param handlerType Type of the handler box object containing the handler that applies to the
25 | * new instance, or undefined if no handler applies.
26 | */
27 | public static fromFile(file: File, header: Mpeg4BoxHeader, handlerType: ByteVector): IsoSampleDescriptionBox {
28 | const instance = new IsoSampleDescriptionBox();
29 | instance.initializeFromHeaderFileAndHandler(header, file, handlerType);
30 | instance.increaseDataPosition(4);
31 | instance._entryCount = file.readBlock(4).toUint();
32 |
33 | return instance;
34 | }
35 |
36 | /**
37 | * The number of boxes at the beginning of the children that will be stored as {@link IsoAudioSampleEntry}
38 | * of {@link IsoVisualSampleEntry} objects, depending on the handler.
39 | */
40 | public get entryCount(): number { return this._entryCount; }
41 | }
42 |
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoSampleEntry.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {File} from "../../file";
4 | import {Guards} from "../../utils";
5 | import {ByteVector} from "../../byteVector";
6 |
7 | /**
8 | * This class extends {@link Mpeg4Box} to provide an implementation of a ISO/IEC 14496-12 SampleEntry.
9 | */
10 | export default abstract class IsoSampleEntry extends Mpeg4Box {
11 | private _dataReferenceIndex: number;
12 |
13 | /**
14 | * Protected constructor to force construction via static functions.
15 | */
16 | protected constructor() {
17 | super();
18 | }
19 |
20 | /**
21 | * Constructs and initializes a new instance of {@link IsoSampleEntry} with a provided header and
22 | * handler by reading the contents from a specified file.
23 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
24 | * @param file A {@link File} object to read the contents of the box from.
25 | * @param handlerType Type of the handler box object containing the handler that applies to the
26 | * new instance, or undefined if no handler applies.
27 | */
28 | public initializeFromHeaderFileAndHandler(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): void {
29 | Guards.truthy(file, "file");
30 |
31 | this.initializeFromHeader(header, handlerType);
32 | const dataPositionBeforeIncrease = this.increaseDataPosition(8);
33 | file.seek(dataPositionBeforeIncrease + 6);
34 | this._dataReferenceIndex = file.readBlock(2).toUshort();
35 | }
36 |
37 | /**
38 | * Gets the data reference index of the current instance.
39 | */
40 | public get dataReferenceIndex(): number { return this._dataReferenceIndex; }
41 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoSampleTableBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector} from "../../byteVector";
4 |
5 | /**
6 | * This class extends {@link Mpeg4Box} to provide an implementation of a ISO/IEC 14496-12 SampleTableBox.
7 | */
8 | export default class IsoSampleTableBox extends Mpeg4Box {
9 | /**
10 | * Private constructor to force construction via static functions.
11 | */
12 | private constructor() {
13 | super();
14 | }
15 |
16 | /**
17 | * Constructs and initializes a new instance of {@link IsoSampleTableBox} with a provided header and
18 | * handler by reading the contents from a specified file.
19 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
20 | * @param handlerType Type of the handler box object containing the handler that applies to the
21 | * new instance, or undefined if no handler applies.
22 | * @returns A new instance of {@link IsoSampleTableBox}
23 | */
24 | public static fromHeader(header: Mpeg4BoxHeader, handlerType: ByteVector): IsoSampleTableBox {
25 | const instance = new IsoSampleTableBox();
26 | instance.initializeFromHeader(header, handlerType);
27 |
28 | return instance;
29 | }
30 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoUnknownSampleEntry.ts:
--------------------------------------------------------------------------------
1 | import IsoSampleEntry from "./isoSampleEntry";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {File} from "../../file";
4 | import {ByteVector} from "../../byteVector";
5 |
6 | /**
7 | * This class extends {@link Mpeg4Box} to provide an implementation of a ISO/IEC 14496-12 SampleEntry.
8 | */
9 | export default class IsoUnknownSampleEntry extends IsoSampleEntry {
10 | /**
11 | * Protected constructor to force construction via static functions.
12 | */
13 | private constructor() {
14 | super();
15 | }
16 |
17 | /**
18 | * Constructs and initializes a new instance of {@link IsoUnknownSampleEntry} with a provided header and
19 | * handler by reading the contents from a specified file.
20 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
21 | * @param file A {@link File} to read the contents of the box from.
22 | * new instance, or undefined if no handler applies.
23 | * @param handlerType Type of the handler box object containing the handler that applies to the
24 | * new instance, or undefined if no handler applies.
25 | */
26 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): IsoUnknownSampleEntry {
27 | const instance = new IsoUnknownSampleEntry();
28 | instance.initializeFromHeaderFileAndHandler(header, file, handlerType);
29 | return instance;
30 | }
31 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoUserDataBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import Mpeg4BoxType from "../mpeg4BoxType";
4 | import {ByteVector} from "../../byteVector";
5 |
6 | /**
7 | * This class extends {@link Mpeg4Box} to provide an implementation of a ISO/IEC 14496-12 UserDataBox.
8 | */
9 | export default class IsoUserDataBox extends Mpeg4Box {
10 | private _parentTree: Mpeg4BoxHeader[];
11 |
12 | /**
13 | * Private constructor to force construction via static functions.
14 | */
15 | private constructor() {
16 | super();
17 | }
18 |
19 | /**
20 | * Constructs and initializes a new instance of {@link IsoUserDataBox} with a provided header and
21 | * handler by reading the contents from a specified file.
22 | * @param header A {@link Mpeg4BoxHeader} object containing the header to use for the new instance.
23 | * @param handlerType Type of the handler box object containing the handler that applies to the
24 | * new instance, or undefined if no handler applies.
25 | */
26 | public static fromHeader(header: Mpeg4BoxHeader, handlerType: ByteVector): IsoUserDataBox {
27 | const instance = new IsoUserDataBox();
28 | instance.initializeFromHeader(header, handlerType);
29 |
30 | return instance;
31 | }
32 |
33 | /**
34 | * Constructs and initializes a new instance of @see IsoUserDataBox with no children.
35 | */
36 | public static fromEmpty(): IsoUserDataBox {
37 | const instance = new IsoUserDataBox();
38 | instance.initializeFromType(Mpeg4BoxType.UDTA);
39 |
40 | return instance;
41 | }
42 |
43 | /**
44 | * Gets the box headers for the current "udta" box and all parent boxes up to the top of the file.
45 | * @remarks Changes to the returned object will not be honored. Set the property to change it.
46 | */
47 | public get parentTree(): Mpeg4BoxHeader[] { return this._parentTree.slice(); }
48 | /**
49 | * Sets the box headers for the current "udta" box and all parent boxes up to the top of the file.
50 | * @internal
51 | */
52 | public set parentTree(v: Mpeg4BoxHeader[]) { this._parentTree = v; }
53 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/isoVisualSampleEntry.ts:
--------------------------------------------------------------------------------
1 | import IsoSampleEntry from "./isoSampleEntry";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector, StringType} from "../../byteVector";
4 | import {File} from "../../file";
5 | import {IVideoCodec, MediaTypes} from "../../properties";
6 |
7 | /**
8 | * This class extends {@link IsoSampleEntry} and implements {@link IVideoCodec} to provide an implementation of a
9 | * ISO/IEC 14496-12 VisualSampleEntry and support for reading MPEG-4 video properties.
10 | */
11 | export default class IsoVisualSampleEntry extends IsoSampleEntry implements IVideoCodec {
12 | private _videoHeight: number;
13 | private _videoWidth: number;
14 |
15 | /**
16 | * Private constructor to force construction via static functions.
17 | */
18 | private constructor() {
19 | super();
20 | }
21 |
22 | /**
23 | * Initializes the instance using the box's header, and additional information read from the file.
24 | * @param header Header for the box.
25 | * @param file File to read additional information from.
26 | * @param handlerType Type of the handler for the box. Optional.
27 | */
28 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): IsoVisualSampleEntry {
29 | const instance = new IsoVisualSampleEntry();
30 | instance.initializeFromHeaderFileAndHandler(header, file, handlerType);
31 |
32 | const dataPositionBeforeIncrease = instance.increaseDataPosition(62);
33 | file.seek(dataPositionBeforeIncrease + 16);
34 | instance._videoWidth = file.readBlock(2).toUshort();
35 | instance._videoHeight = file.readBlock(2).toUshort();
36 |
37 | return instance;
38 | }
39 |
40 | /** @inheritDoc */
41 | public get durationMilliseconds(): number { return 0; }
42 |
43 | /** @inheritDoc */
44 | public get mediaTypes(): MediaTypes { return MediaTypes.Video; }
45 |
46 | /** @inheritDoc */
47 | // @TODO: I'm sure we can get a better description than this
48 | public get description(): string { return `MPEG-4 Video (${this.boxType.toString(StringType.Latin1)})`; }
49 |
50 | /** @inheritDoc */
51 | public get videoHeight(): number { return this._videoHeight; }
52 |
53 | /** @inheritDoc */
54 | public get videoWidth(): number { return this._videoWidth; }
55 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/textBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector} from "../../byteVector";
4 | import {File} from "../../file";
5 |
6 | /**
7 | * Represents an MP4 text box
8 | */
9 | export default class TextBox extends Mpeg4Box {
10 | /**
11 | * Private constructor to force construction via static functions.
12 | */
13 | private constructor() {
14 | super();
15 | }
16 |
17 | /**
18 | * Constructs and initializes a new instance of @see TextBox with a provided header and handler
19 | * by reading the contents from a specified file.
20 | * @param header A @see Mpeg4BoxHeader object containing the header to use for the new instance.
21 | * @param file A @see File object to read the contents of the box from.
22 | * @param handlerType Type of the handler box object containing the handler that applies to the
23 | * new instance, or undefined if no handler applies.
24 | */
25 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): TextBox {
26 | const instance = new TextBox();
27 | instance.initializeFromHeader(header, handlerType);
28 | instance.data = instance.loadData(file);
29 |
30 | return instance;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/unknownBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector} from "../../byteVector";
4 | import {File} from "../../file";
5 |
6 | export default class UnknownBox extends Mpeg4Box {
7 | /**
8 | * Private constructor to force construction via static functions.
9 | */
10 | private constructor() {
11 | super();
12 | }
13 |
14 | /**
15 | * Constructs and initializes a new instance of @see UnknownBox with a provided header and handler
16 | * by reading the contents from a specified file.
17 | * @param header A @see Mpeg4BoxHeader object containing the header to use for the new instance.
18 | * @param file A @see File object to read the contents of the box from.
19 | * @param handlerType Type of the handler box object containing the handler that applies to the
20 | * new instance, or undefined if no handler applies.
21 | */
22 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): UnknownBox {
23 | const instance = new UnknownBox();
24 | instance.initializeFromHeader(header, handlerType);
25 | instance.data = file.readBlock(instance.dataSize > 0 ? instance.dataSize : 0);
26 |
27 | return instance;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/mpeg4/boxes/urlBox.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4Box from "./mpeg4Box";
2 | import Mpeg4BoxHeader from "../mpeg4BoxHeader";
3 | import {ByteVector} from "../../byteVector";
4 | import {File} from "../../file";
5 |
6 | /**
7 | * Represent a MP4 URL box
8 | */
9 | export default class UrlBox extends Mpeg4Box {
10 | /**
11 | * Private constructor to force construction via static functions.
12 | */
13 | private constructor() {
14 | super();
15 | }
16 |
17 | /**
18 | * Constructs and initializes a new instance of @see UrlBox with a provided header and handler
19 | * by reading the contents from a specified file.
20 | * @param header A @see Mpeg4BoxHeader object containing the header to use for the new instance.
21 | * @param file A @see File object to read the contents of the box from.
22 | * @param handlerType Type of the handler box object containing the handler that applies to the
23 | * new instance, or undefined if no handler applies.
24 | */
25 | public static fromFile(header: Mpeg4BoxHeader, file: File, handlerType: ByteVector): UrlBox {
26 | const instance = new UrlBox();
27 | instance.initializeFromHeader(header, handlerType);
28 | instance.data = instance.loadData(file);
29 |
30 | return instance;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/mpeg4/descriptorTag.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Descriptor Tags
3 | */
4 | export enum DescriptorTag {
5 | Forbidden0 = 0,
6 | ObjectDescriptorTag = 1,
7 | InitialObjectDescriptorTag = 2,
8 | EsDescriptorTag = 3,
9 | DecoderConfigDescriptorTag = 4,
10 | DecSpecificInfoTag = 5,
11 | SlConfigDescriptorTag = 6,
12 | ContentIdentDescriptorTag = 7,
13 | SupplContentIdentDescriptorTag = 8,
14 | IpiDescriptorPointerTag = 9,
15 | IpmpDescriptorPointerTag = 10,
16 | IpmpDescriptorTag = 11,
17 | QosDescriptorTag = 12,
18 | RegistrationDescriptorTag = 13,
19 | EsIdIncTag = 14,
20 | EsIdRefTag = 15,
21 | Mp4IodTag = 16,
22 | Mp4OdTag = 17,
23 | IplDescriptorPointerRefTag = 18,
24 | ExtensionProfileLevelDescriptorTag = 19,
25 | ProfileLevelIndicationIndexDescriptorTag = 20,
26 | // Reserved for future ISO use 0x15 to 0x3F
27 | ContentClassificationDescriptorTag = 64,
28 | KeyWordDescriptorTag = 65,
29 | RatingDescriptorTag = 66,
30 | LanguageDescriptorTag = 67,
31 | ShortTextualDescriptorTag = 68,
32 | ExpandedTextualDescriptorTag = 69,
33 | ContentCreatorNameDescriptorTag = 70,
34 | ContentCreationDateDescriptorTag = 71,
35 | OciCreatorNameDescriptorTag = 72,
36 | OciCreationDateDescriptorTag = 73,
37 | SmpteCameraPositionDescriptorTag = 74,
38 | SegmentDescriptorTag = 75,
39 | MediaTimeDescriptorTag = 76,
40 | // Reserved for future ISO use 0x4D to 0x5F
41 | IpmpToolsListDescriptorTag = 96,
42 | IpmpToolTag = 97,
43 | M4MuxTimingDescriptorTag = 98,
44 | M4MuxCodeTableDescriptorTag = 99,
45 | ExtSLConfigDescriptorTag = 100,
46 | M4MuxBufferSizeDescriptorTag = 101,
47 | M4MuxIdentDescriptorTag = 102,
48 | DependencyPointerTag = 103,
49 | DependencyMarkerTag = 104,
50 | M4MuxChannelDescriptorTag = 105,
51 | // Reserved for future ISO use 0x6A to 0xBF
52 | UserPrivate = 192,
53 | Forbidden255 = 255,
54 | }
55 |
--------------------------------------------------------------------------------
/src/mpeg4/descriptorTagReader.ts:
--------------------------------------------------------------------------------
1 | import { ByteVector } from "../byteVector";
2 | import {Guards, NumberUtils} from "../utils";
3 |
4 | /**
5 | * Provides methods to read descriptor tags
6 | * @internal
7 | */
8 | export class DescriptorTagReader {
9 | private _data: ByteVector;
10 | private _length: number;
11 | private _offset: number;
12 |
13 | /**
14 | * Constructs and initializes a new descriptor tag reader with the data from which to read the
15 | * descriptor tag.
16 | * @param data Data from which the descriptor tag should be read
17 | */
18 | public constructor(data: ByteVector) {
19 | Guards.truthy(data, "data");
20 |
21 | this._data = data;
22 | this._length = 0;
23 | this._offset = 0;
24 | }
25 |
26 | /**
27 | * Gets the length of the descriptor tag.
28 | */
29 | public get length(): number { return this._length; }
30 |
31 | /**
32 | * Gets the offset of the descriptor tag.
33 | */
34 | public get offset(): number { return this._offset; }
35 |
36 | /**
37 | * Reads a section length and updates the offset to the end of the length block.
38 | * @returns number Length that was read.
39 | */
40 | public readLength(): number {
41 | let b = 0;
42 | const end = this._offset + 4;
43 |
44 | do {
45 | b = this._data.get(this._offset++);
46 | this._length = NumberUtils.uintOr(NumberUtils.uintLShift(this._length, 7), NumberUtils.uintAnd(b, 0x7f));
47 | } while (NumberUtils.uintAnd(b, 0x80) !== 0 && this._offset <= end);
48 | // The length could be between 1 and 4 bytes for each descriptor
49 |
50 | return this._length;
51 | }
52 |
53 | /**
54 | * Increases the current offset by a given value
55 | * @param value A number by which the offset should be increased
56 | * @returns number Offset before increase
57 | */
58 | public increaseOffset(value: number): number {
59 | Guards.safeUint(value, "value");
60 |
61 | const previousOffset = this._offset;
62 | this._offset += value;
63 |
64 | return previousOffset;
65 | }
66 | }
--------------------------------------------------------------------------------
/src/mpeg4/mpeg4AudioTypes.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * MPEG-4 audio object types as defined in https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Audio_Object_Types .
3 | * Index corresponds to the value of the object type.
4 | */
5 | export default [
6 | "Null",
7 | "AAC Main",
8 | "AAC LC (Low Complexity)",
9 | "AAC SSR (Scalable Sample Rate)",
10 | "AAC LTP (Long-Term Prediction)",
11 | "SBR (Spectral Band Replication)",
12 | "AAC Scalable",
13 | "TwinVQ",
14 | "CELP (Code Excited Linear Prediction)",
15 | "HXVC (Harmonic Vector eXcitation Coding)",
16 | "Reserved",
17 | "Reserved",
18 | "TTSI (Text-To-Speech Interface)",
19 | "Main Synthesis",
20 | "Wavetable Synthesis",
21 | "General MIDI",
22 | "Algorithmic Synthesis and Audio Effects",
23 | "Error Resilient AAC LC (Low Complexity)",
24 | "Reserved",
25 | "Error Resilient AAC LTP (Long-Term Prediction)",
26 | "Error Resilient AAC Scalable",
27 | "Error Resilient TwinVQ",
28 | "Error Resilient BSAC (Bit-Sliced Arithmetic Coding)",
29 | "Error Resilient AAC LD (Low Delay)",
30 | "Error Resilient CELP (Code Excited Linear Prediction)",
31 | "Error Resilient HXVC (Harmonic Vector eXcitation Coding)",
32 | "Error Resilient HILN (Harmonic and Individual Lines plus Noise)",
33 | "Error Resilient Parametric",
34 | "SSC (SinuSoidal Coding)",
35 | "PS (Parametric Stereo)",
36 | "MPEG Surround",
37 | "(escape value)",
38 | "Layer-1",
39 | "Layer-2",
40 | "Layer-3",
41 | "DST (Direct Stream Transfer)",
42 | "ALS (Audio Lossless)",
43 | "SLS (Scalable Lossless)",
44 | "SLS non-core",
45 | "Error Resilient AAC ELD (Enhanced Low Delay)",
46 | "SMR (Symbolic Music Representation) Simple",
47 | "SMR (Symbolic Music Representation) Main",
48 | "USAC (Unified Speech and Audio Coding) (no SBR)",
49 | "SAOC (Spatial Audio Object Coding)",
50 | "Low Delay MPEG Surround",
51 | "USAC (Unified Speech and Audio Coding)"
52 | ];
53 |
--------------------------------------------------------------------------------
/src/mpeg4/mpeg4BoxRenderer.ts:
--------------------------------------------------------------------------------
1 | import IsoFreeSpaceBox from "./boxes/isoFreeSpaceBox";
2 | import Mpeg4Box from "./boxes/mpeg4Box";
3 | import Mpeg4BoxType from "./mpeg4BoxType";
4 | import {ByteVector} from "../byteVector";
5 | import {Guards} from "../utils";
6 |
7 | /**
8 | * Renderer for {@link Mpeg4Box} objects.
9 | * @remarks Written this way to break a circular dependency from child {@link Mpeg4Box} classes and
10 | * the root {@link Mpeg4Box} class.
11 | */
12 | export default class Mpeg4BoxRenderer {
13 | /**
14 | * Renders the provided `box` for output into a file.
15 | * @param box Box to render
16 | * @returns ByteVector Box as rendered for output into a file.
17 | */
18 | public static renderBox(box: Mpeg4Box): ByteVector {
19 | Guards.truthy(box, "box");
20 |
21 | let freeFound = false;
22 | const outputVectors: ByteVector[] = [];
23 |
24 | // Write children or data
25 | if (box.hasChildren) {
26 | for (const child of box.children) {
27 | if (box instanceof IsoFreeSpaceBox) {
28 | freeFound = true;
29 | } else {
30 | outputVectors.push(this.renderBox(child));
31 | }
32 | }
33 | } else if (box.data) {
34 | // @TODO: If the box generates the data property on get, we should change it to a render method.
35 | outputVectors.push(box.data);
36 | }
37 |
38 | // If there was a free, don't take it away, and let meta be a special case
39 | if (freeFound || ByteVector.equals(box.boxType, Mpeg4BoxType.META)) {
40 | const newSizeSoFar = outputVectors.reduce((accum, current) => accum + current.length, 0);
41 | const sizeDifference = box.dataSize - newSizeSoFar;
42 | let newPadding: IsoFreeSpaceBox;
43 | if (box.header.dataSize !== 0 && sizeDifference >= 8) {
44 | // If we have room for free space, add it so we don't have to resize the file
45 | newPadding = IsoFreeSpaceBox.fromPadding(sizeDifference);
46 | } else {
47 | // If we're getting bigger, get a lot bigger so we might not have to do this again
48 | newPadding = IsoFreeSpaceBox.fromPadding(2048);
49 | }
50 |
51 | outputVectors.push(this.renderBox(newPadding));
52 | }
53 |
54 |
55 | // Handle the box-specific headers
56 | const boxHeaders = box.renderBoxHeaders();
57 | if (boxHeaders?.length > 0) {
58 | outputVectors.splice(0, 0, ...boxHeaders);
59 | }
60 |
61 | // Adjust the data's header size for the new content, render the header
62 | box.header.dataSize = outputVectors.reduce((accum, current) => accum + current.length, 0);
63 | outputVectors.splice(0, 0, box.header.render());
64 |
65 | return ByteVector.concatenate(...outputVectors);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/mpeg4/mpeg4HandlerType.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector, StringType} from "../byteVector";
2 |
3 | /**
4 | * These are some of the handler types.
5 | * @remarks Two sources for these handlers are:
6 | * * https://cconcolato.github.io/mp4ra/handler.html#
7 | * * https://exiftool.org/TagNames/QuickTime.html#Meta
8 | */
9 | export default class Mpeg4HandlerType {
10 | /** Quicktime Alias */
11 | public static readonly ALIS = ByteVector.fromString("alis", StringType.UTF8).makeReadOnly();
12 | /** Quicktime Metadata */
13 | public static readonly MDIR = ByteVector.fromString("mdir", StringType.UTF8).makeReadOnly();
14 | /** Audio */
15 | public static readonly SOUN = ByteVector.fromString("soun", StringType.UTF8).makeReadOnly();
16 | /** Video **/
17 | public static readonly VIDE = ByteVector.fromString("vide", StringType.UTF8).makeReadOnly();
18 | }
--------------------------------------------------------------------------------
/src/mpeg4/mpeg4Utils.ts:
--------------------------------------------------------------------------------
1 | import Mpeg4BoxHeader from "./mpeg4BoxHeader";
2 |
3 | /**
4 | * Collection of utilities for interacting with MPEG4 files.
5 | * @internal
6 | */
7 | export default class Mpeg4Utils {
8 | /**
9 | * Adds a parent to the end of an existing list of parents.
10 | * @param parents A {@link Mpeg4BoxHeader[]} object containing an existing list of parents.
11 | * @param current A {@link Mpeg4BoxHeader} object to add to the list.
12 | * @returns Mpeg4BoxHeader[] List of parents, including the added header.
13 | */
14 | public static addParent(parents: Mpeg4BoxHeader[], current: Mpeg4BoxHeader): Mpeg4BoxHeader[] {
15 | const boxes: Mpeg4BoxHeader[] = [];
16 |
17 | if (parents) {
18 | boxes.push(...parents);
19 | }
20 |
21 | boxes.push(current);
22 |
23 | return boxes;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ogg/codecs/iOggCodec.ts:
--------------------------------------------------------------------------------
1 | import XiphComment from "../../xiph/xiphComment";
2 | import {ByteVector} from "../../byteVector";
3 | import {ICodec} from "../../properties";
4 |
5 | /**
6 | * Interface for an OGG codec.
7 | */
8 | export default interface IOggCodec extends ICodec {
9 | /**
10 | * Gets the raw Xiph comment data contained in the codec.
11 | */
12 | get commentData(): ByteVector;
13 |
14 | /**
15 | * Reads an Ogg packet that has been encountered in the stream, looking for the comment data.
16 | * @param packet Packet to read
17 | * @returns
18 | * `true` if the codec has read all the necessary packets for the stream and
19 | * does not need to be called again,
20 | */
21 | readPacket(packet: ByteVector): boolean;
22 |
23 | /**
24 | * Sets the file offset information necessary for calculating the duration of the stream. Once
25 | * called, the duration can be accessed by calling {@link ICodec.durationMilliseconds}.
26 | * @param firstGranularPosition First granular position of the stream
27 | * @param lastGranularPosition Last granular position of the stream
28 | */
29 | setDuration(firstGranularPosition: ByteVector, lastGranularPosition: ByteVector): void;
30 |
31 | /**
32 | * Renders and write the provided comment into the provided list of packets.
33 | * @param packets List of packets the comment packet should be written into.
34 | * @param comment Xiph comment to write into the list of packets.
35 | */
36 | writeCommentPacket(packets: ByteVector[], comment: XiphComment): void;
37 | }
38 |
--------------------------------------------------------------------------------
/src/ogg/oggFileSettings.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This class contains settings related to Ogg file operations. Open files will need to be re-read
3 | * in order for changes to take effect.
4 | */
5 | export default class OggFileSettings {
6 | private static _writeToAllComments = false;
7 |
8 | /**
9 | * Gets whether changes to Ogg tag fields should be written to all Xiph comments or just the
10 | * first Xiph comment in the file.
11 | * @remarks
12 | * Ogg files are required to have one Xiph comment per stream. In files with multiple
13 | * streams, this means there are multiple Xiph comments per file.
14 | */
15 | public static get writeToAllComments(): boolean { return this._writeToAllComments; }
16 | /**
17 | * Sets whether changes to Ogg tag fields should be written to all Xiph comments or just the
18 | * first Xiph comment in the file.
19 | * @remarks
20 | * Ogg files are required to have one Xiph comment per stream. In files with multiple
21 | * streams, this means there are multiple Xiph comments per file.
22 | */
23 | public static set writeToAllComments(value: boolean) { this._writeToAllComments = value; }
24 | }
25 |
--------------------------------------------------------------------------------
/src/riff/aviFileSettings.ts:
--------------------------------------------------------------------------------
1 | import {TagTypes} from "../tag";
2 | import {NumberUtils} from "../utils";
3 |
4 | /**
5 | * This class contains settings related to AVI file operations. Open files will need to be re-read
6 | * in order for changes to take effect.
7 | */
8 | export default class AviFileSettings {
9 | /**
10 | * The types of tags that are supported by AVI files.
11 | */
12 | public static readonly SUPPORTED_TAG_TYPES = TagTypes.DivX | TagTypes.Id3v2 | TagTypes.RiffInfo | TagTypes.MovieId;
13 |
14 | private static _defaultTagTypes = AviFileSettings.SUPPORTED_TAG_TYPES;
15 |
16 | /**
17 | * Gets the default types of tags for an AVI file. When opening a file, if these tag types do
18 | * not exist on the file, they will be created.
19 | */
20 | public static get defaultTagTypes(): TagTypes { return this._defaultTagTypes; }
21 |
22 | /**
23 | * Sets the default types of tags for an AVI file. When opening a file, if these tag types do
24 | * not exist on the file, they will be created. See {@link SUPPORTED_TAG_TYPES} for a list of tag
25 | * types that are supported by node-taglib-sharp for AVI files.
26 | */
27 | public static set defaultTagTypes(value: TagTypes) {
28 | const unsupportedTagTypes = NumberUtils.uintAnd(value, ~this.SUPPORTED_TAG_TYPES);
29 | if (unsupportedTagTypes !== 0) {
30 | throw new Error(
31 | `Argument error: node-taglib-sharp does not support tag types ${unsupportedTagTypes} for AVI files`
32 | );
33 | }
34 |
35 | this._defaultTagTypes = value;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/riff/iRiffChunk.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector} from "../byteVector";
2 |
3 | /**
4 | * Interface for chunks that appear in a RIFF file.
5 | */
6 | export default interface IRiffChunk {
7 | /**
8 | * Offset into the file where the chunk begins. This is `undefined` if the object was
9 | * constructed directly from data.
10 | */
11 | chunkStart: number|undefined;
12 |
13 | /**
14 | * FOURCC code for the chunk.
15 | */
16 | fourcc: string;
17 |
18 | /**
19 | * Size of just the data contained within the current instance. Does not include the header or
20 | * padding byte. This value does not update if contents of the chunk changes.
21 | */
22 | originalDataSize: number;
23 |
24 | /**
25 | * Original size of the chunk, including header and padding byte. This value does not update if
26 | * the contents of the chunk changes.
27 | */
28 | originalTotalSize: number;
29 |
30 | /**
31 | * Renders the chunk, including the header and padding byte.
32 | */
33 | render(): ByteVector;
34 | }
35 |
--------------------------------------------------------------------------------
/src/riff/riffTags.ts:
--------------------------------------------------------------------------------
1 | import CombinedTag from "../combinedTag";
2 | import {Tag, TagTypes} from "../tag";
3 | import DivxTag from "./divxTag";
4 | import Id3v2Tag from "../id3v2/id3v2Tag";
5 | import InfoTag from "./infoTag";
6 | import MovieIdTag from "./movieIdTag";
7 | import {Id3v2TagHeaderFlags} from "..";
8 | import {UnsupportedFormatError} from "../errors";
9 |
10 | export default class RiffTags extends CombinedTag {
11 | public static readonly SUPPORTED_TAG_TYPES = TagTypes.DivX | TagTypes.Id3v2 | TagTypes.RiffInfo | TagTypes.MovieId;
12 |
13 | public constructor(divxTag: DivxTag, id3v2Tag: Id3v2Tag, infoTag: InfoTag, movieIdTag: MovieIdTag) {
14 | super(RiffTags.SUPPORTED_TAG_TYPES, true);
15 |
16 | // NOTE: We're adding ID3 first because it is the most flexible tagging format. Divx is last
17 | // because it is the least flexible tagging format.
18 | this.addTag(id3v2Tag);
19 | this.addTag(infoTag);
20 | this.addTag(movieIdTag);
21 | this.addTag(divxTag);
22 | }
23 |
24 | /** @inheritDoc */
25 | public createTag(tagType: TagTypes, copy: boolean): Tag {
26 | this.validateTagCreation(tagType);
27 |
28 | // Create the desired tag
29 | let tag: Tag;
30 | switch (tagType) {
31 | case TagTypes.DivX:
32 | tag = DivxTag.fromEmpty();
33 | break;
34 | case TagTypes.Id3v2:
35 | const id3v2Tag = Id3v2Tag.fromEmpty();
36 | // @TODO: have default version be configurable
37 | id3v2Tag.version = 4;
38 | id3v2Tag.flags |= Id3v2TagHeaderFlags.FooterPresent;
39 | tag = id3v2Tag;
40 | break;
41 | case TagTypes.RiffInfo:
42 | tag = InfoTag.fromEmpty();
43 | break;
44 | case TagTypes.MovieId:
45 | tag = MovieIdTag.fromEmpty();
46 | break;
47 | default:
48 | throw new UnsupportedFormatError(`Specified tag type ${tagType} is invalid`);
49 | }
50 |
51 |
52 | // Copy the contents of this tag to the new tag if desired
53 | if (copy) {
54 | this.copyTo(tag, true);
55 | }
56 |
57 | this.addTag(tag);
58 | return tag;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/riff/waveFileSettings.ts:
--------------------------------------------------------------------------------
1 | import {TagTypes} from "../tag";
2 | import {NumberUtils} from "../utils";
3 |
4 | /**
5 | * This class contains settings related to WAV file operations. Open files will need to be re-read
6 | * in order for changes to take effect.
7 | */
8 | export default class WaveFileSettings {
9 | /**
10 | * The types of tags that are supported by WAV files.
11 | */
12 | public static readonly SUPPORTED_TAG_TYPES = TagTypes.DivX | TagTypes.Id3v2 | TagTypes.RiffInfo | TagTypes.MovieId;
13 |
14 | private static _defaultTagTypes = WaveFileSettings.SUPPORTED_TAG_TYPES;
15 |
16 | /**
17 | * Gets the default types of tags for an WAV file. When opening a file, if these tag types do
18 | * not exist on the file, they will be created.
19 | */
20 | public static get defaultTagTypes(): TagTypes { return this._defaultTagTypes; }
21 |
22 | /**
23 | * Sets the default types of tags for an WAV file. When opening a file, if these tag types do
24 | * not exist on the file, they will be created. See {@link SUPPORTED_TAG_TYPES} for a list of tag
25 | * types that are supported by node-taglib-sharp for WAV files.
26 | */
27 | public static set defaultTagTypes(value: TagTypes) {
28 | const unsupportedTagTypes = NumberUtils.uintAnd(value, ~this.SUPPORTED_TAG_TYPES);
29 | if (unsupportedTagTypes !== 0) {
30 | throw new Error(
31 | `Argument error: node-taglib-sharp does not support tag types ${unsupportedTagTypes} for AVI files`
32 | );
33 | }
34 |
35 | this._defaultTagTypes = value;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/sandwich/tagParsers.ts:
--------------------------------------------------------------------------------
1 | import {Tag} from "../tag";
2 | import {File, ReadStyle} from "../file";
3 |
4 | /**
5 | * Common logic for parsing sequential tags at the start or end of a file. Classes that inherit
6 | * from this class are expected to provide `while(parser.read())` functionality. If {@link read}
7 | * returns `true` the tag that was just read can be read from {@link currentTag}.
8 | */
9 | export default abstract class TagParser {
10 | // @TODO: Don't allow access to member variables
11 | private readonly _file: File;
12 | private readonly _readStyle: ReadStyle;
13 | private _currentTag: Tag;
14 | private _fileOffset: number;
15 |
16 | protected constructor(file: File, readStyle: ReadStyle, initialOffset: number) {
17 | this._file = file;
18 | this._fileOffset = initialOffset;
19 | this._readStyle = readStyle;
20 | }
21 |
22 | /**
23 | * Tag that was just read from the file. This will be `undefined` until {@link read} is called.
24 | * The value is not guaranteed if {@link read} returns `false`
25 | */
26 | public get currentTag(): Tag { return this._currentTag; }
27 | protected set currentTag(value: Tag) { this._currentTag = value; }
28 |
29 | protected get file(): File { return this._file; }
30 |
31 | protected get fileOffset(): number { return this._fileOffset; }
32 | protected set fileOffset(value: number) { this._fileOffset = value; }
33 |
34 | protected get readStyle(): ReadStyle { return this._readStyle; }
35 |
36 | /**
37 | * Reads the next tag from the file.
38 | * @returns
39 | * `true` is returned if a tag is found, the tag can be accessed from
40 | * {@link currentTag}. `false` is returned if no tag was found.
41 | */
42 | public abstract read(): boolean;
43 | }
44 |
--------------------------------------------------------------------------------
/src/settings.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * General settings for the node-taglib-sharp libary.
3 | */
4 | export default class Settings {
5 | private static _copyExistingTagsToNewDefaultTags: boolean = true;
6 |
7 | /**
8 | * Gets whether existing tags should be copied into newly created default tags.
9 | * If `true`, tags that already exist in the file will be copied into any newly created default
10 | * tags. If `false`, newly created default tags will be left empty.
11 | */
12 | public static get copyExistingTagsToNewDefaultTags(): boolean { return this._copyExistingTagsToNewDefaultTags; }
13 |
14 | /**
15 | * Sets whether existing tags should be copied into newly created default tags.
16 | * If `true`, tags that already exist in the file will be copied into any newly created default
17 | * tags. If `false`, newly created default tags will be left empty.
18 | */
19 | public static set copyExistingTagsToNewDefaultTags(value: boolean) {
20 | this._copyExistingTagsToNewDefaultTags = value;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/xiph/xiphSettings.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This class contains settings related to Xiph tagging. Open files will need to be re-opened in
3 | * order for changes to take effect.
4 | */
5 | export default class XiphSettings {
6 | private static _useTempoToStoreBpm: boolean = true;
7 |
8 | // noinspection JSUnusedLocalSymbols
9 | /**
10 | * Private constructor to prevent inadvertent construction
11 | */
12 | private constructor() { /* private to prevent constructing instances */ }
13 |
14 | /**
15 | * Gets whether to use "TEMPO" field to store {@link XiphComment.beatsPerMinute} property. If `true`
16 | * "TEMPO" will be used, if `false` "BPM" will be used.
17 | * @default `true`
18 | */
19 | public static get useTempoToStoreBpm(): boolean { return this._useTempoToStoreBpm; }
20 | /**
21 | * Sets whether to use "TEMPO" field to store {@link XiphComment.beatsPerMinute} property. If `true`
22 | * "TEMPO" will be used, if `false` "BPM" will be used.
23 | */
24 | public static set useTempoToStoreBpm(value: boolean) { this._useTempoToStoreBpm = value; }
25 | }
26 |
--------------------------------------------------------------------------------
/test-integration/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": ["../.eslintrc.js"],
3 | "rules": {
4 | "@typescript-eslint/dot-notation": "off",
5 | "@typescript-eslint/explicit-function-return-type": "off",
6 | "@typescript-eslint/naming-convention": "off",
7 | "@typescript-eslint/no-unsafe-argument": "off",
8 | "@typescript-eslint/no-unused-vars": "off"
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/test-integration/aac_fileTests.ts:
--------------------------------------------------------------------------------
1 | import * as Chai from "chai";
2 | import {suite, test} from "@testdeck/mocha";
3 |
4 | import TestConstants from "./utilities/testConstants";
5 | import {File} from "../src";
6 | import {StandardFileTests} from "./utilities/standardFileTests";
7 |
8 | // Setup chai
9 | const assert = Chai.assert;
10 |
11 | @suite class Aac_FileTests {
12 | private static readonly corruptFilePath = TestConstants.getCorruptFilePath("corrupt.aac");
13 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample.aac");
14 | private static readonly tmpFileName = "tmpwrite.aac";
15 |
16 | private static file: File;
17 |
18 | public static before() {
19 | Aac_FileTests.file = File.createFromPath(Aac_FileTests.sampleFilePath);
20 | }
21 |
22 | public static after() {
23 | Aac_FileTests.file.dispose();
24 | }
25 |
26 | @test
27 | public readAudioProperties() {
28 | StandardFileTests.readAudioProperties(Aac_FileTests.file);
29 | assert.approximately(Aac_FileTests.file.properties.audioBitrate, 236, 1);
30 | assert.strictEqual(Aac_FileTests.file.properties.audioSampleRate, 44100);
31 | assert.strictEqual(Aac_FileTests.file.properties.audioChannels, 2);
32 | assert.approximately(Aac_FileTests.file.properties.durationMilliseconds, 5000, 50);
33 | }
34 |
35 | @test
36 | public readTags() {
37 | assert.strictEqual(Aac_FileTests.file.tag.album, "AAC album");
38 | assert.strictEqual(Aac_FileTests.file.tag.firstPerformer, "AAC artist");
39 | assert.strictEqual(Aac_FileTests.file.tag.comment, "AAC comment");
40 | assert.strictEqual(Aac_FileTests.file.tag.firstGenre, "Acid Punk");
41 | assert.strictEqual(Aac_FileTests.file.tag.title, "AAC title");
42 | assert.strictEqual(Aac_FileTests.file.tag.track, 6);
43 | assert.strictEqual(Aac_FileTests.file.tag.year, 1234);
44 | }
45 |
46 | @test
47 | public testCorruptionResistance() {
48 | StandardFileTests.testCorruptionResistance(Aac_FileTests.corruptFilePath);
49 | }
50 |
51 | @test
52 | public writeStandardPictures() {
53 | const tmpFilePath = TestConstants.getTempFilePath(Aac_FileTests.tmpFileName);
54 | StandardFileTests.writeStandardPictures(Aac_FileTests.sampleFilePath, tmpFilePath);
55 | }
56 |
57 | @test
58 | public writeStandardTags() {
59 | const tmpFilePath = TestConstants.getTempFilePath(Aac_FileTests.tmpFileName);
60 | StandardFileTests.writeStandardTags(Aac_FileTests.sampleFilePath, tmpFilePath);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/test-integration/ape_fileTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import ExtendedFileTests from "./utilities/extendedFileTests";
5 | import TestConstants from "./utilities/testConstants";
6 | import {File} from "../src";
7 | import {StandardFileTests} from "./utilities/standardFileTests";
8 |
9 | @suite class Ape_FileTests {
10 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample.ape");
11 | private static readonly tmpFileName = "tmpwrite.ape";
12 |
13 | private static file: File;
14 |
15 | public static before() {
16 | Ape_FileTests.file = File.createFromPath(Ape_FileTests.sampleFilePath);
17 | }
18 |
19 | public static after() {
20 | Ape_FileTests.file.dispose();
21 | }
22 |
23 | @test
24 | public readAudioProperties() {
25 | assert.approximately(Ape_FileTests.file.properties.audioBitrate, 604, 0.5);
26 | assert.strictEqual(Ape_FileTests.file.properties.audioSampleRate, 44100);
27 | assert.strictEqual(Ape_FileTests.file.properties.audioChannels, 2);
28 | assert.approximately(Ape_FileTests.file.properties.durationMilliseconds, 5230, 10);
29 | }
30 |
31 | @test
32 | public readTags() {
33 | assert.strictEqual(Ape_FileTests.file.tag.album, "APE album");
34 | assert.strictEqual(Ape_FileTests.file.tag.firstPerformer, "APE artist");
35 | assert.strictEqual(Ape_FileTests.file.tag.comment, "APE comment");
36 | assert.strictEqual(Ape_FileTests.file.tag.firstGenre, "Acid Punk");
37 | assert.strictEqual(Ape_FileTests.file.tag.track, 6);
38 | assert.strictEqual(Ape_FileTests.file.tag.trackCount, 7);
39 | assert.strictEqual(Ape_FileTests.file.tag.year, 1234);
40 | }
41 |
42 | @test
43 | public writeExtendedTags() {
44 | const tmpFilePath = TestConstants.getTempFilePath(Ape_FileTests.tmpFileName);
45 | ExtendedFileTests.writeExtendedTags(Ape_FileTests.sampleFilePath, tmpFilePath);
46 | }
47 |
48 | @test
49 | public writeStandardPictures() {
50 | const tmpFilePath = TestConstants.getTempFilePath(Ape_FileTests.tmpFileName);
51 | StandardFileTests.writeStandardPictures(Ape_FileTests.sampleFilePath, tmpFilePath);
52 | }
53 |
54 | @test
55 | public writeStandardTags() {
56 | const tmpFilePath = TestConstants.getTempFilePath(Ape_FileTests.tmpFileName);
57 | StandardFileTests.writeStandardTags(Ape_FileTests.sampleFilePath, tmpFilePath);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/test-integration/matroska_fileTests.ts:
--------------------------------------------------------------------------------
1 | import {assert} from "chai";
2 | import {suite, test} from "@testdeck/mocha";
3 |
4 | import TestConstants from "./utilities/testConstants";
5 | import {File, MediaTypes} from "../src";
6 |
7 | @suite class Matroska_FileTests {
8 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample.mkv");
9 |
10 | private static file: File;
11 |
12 | public static before() {
13 | Matroska_FileTests.file = File.createFromPath(Matroska_FileTests.sampleFilePath);
14 | }
15 |
16 | public static after() {
17 | Matroska_FileTests.file?.dispose();
18 | }
19 |
20 | @test
21 | public readProperties() {
22 | assert.strictEqual(Matroska_FileTests.file.properties.mediaTypes, MediaTypes.Audio | MediaTypes.Video);
23 | assert.strictEqual(Matroska_FileTests.file.properties.audioBitrate, 0);
24 | assert.strictEqual(Matroska_FileTests.file.properties.audioChannels, 1);
25 | assert.strictEqual(Matroska_FileTests.file.properties.audioSampleRate, 48000);
26 | assert.strictEqual(Matroska_FileTests.file.properties.bitsPerSample, 0);
27 | assert.strictEqual(Matroska_FileTests.file.properties.durationMilliseconds, 1120);
28 | assert.strictEqual(Matroska_FileTests.file.properties.videoHeight, 480);
29 | assert.strictEqual(Matroska_FileTests.file.properties.videoWidth, 640);
30 | }
31 |
32 | @test
33 | public readTags() {
34 | assert.strictEqual(Matroska_FileTests.file.tag.firstPerformer, "Lime");
35 | assert.strictEqual(Matroska_FileTests.file.tag.comment, "no comments");
36 | assert.strictEqual(Matroska_FileTests.file.tag.firstGenre, "Test");
37 | assert.strictEqual(Matroska_FileTests.file.tag.year, 2017);
38 | assert.strictEqual(Matroska_FileTests.file.tag.firstComposer, "Starwer");
39 | assert.strictEqual(Matroska_FileTests.file.tag.conductor, "Starwer");
40 | assert.strictEqual(Matroska_FileTests.file.tag.copyright, "Starwer 2017");
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/test-integration/mp3_id3v1_fileTests.ts:
--------------------------------------------------------------------------------
1 | import * as Chai from "chai";
2 | import {suite, test} from "@testdeck/mocha";
3 |
4 | import TestConstants from "./utilities/testConstants";
5 | import {File, ReadStyle} from "../src";
6 | import {StandardFileTests} from "./utilities/standardFileTests";
7 |
8 | // Setup chai
9 | const assert = Chai.assert;
10 |
11 | @suite class Mp3_id3v1_fileTests {
12 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample_v1_only.mp3");
13 | private static readonly tmpFileName = "tmpwrite_v1_only.mp3";
14 |
15 | private static file: File;
16 |
17 | public static before() {
18 | Mp3_id3v1_fileTests.file = File.createFromPath(Mp3_id3v1_fileTests.sampleFilePath);
19 | }
20 |
21 | public static after() {
22 | Mp3_id3v1_fileTests.file.dispose();
23 | }
24 |
25 | @test
26 | public readTags() {
27 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.album, "MP3 album");
28 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.firstPerformer, "MP3 artist");
29 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.comment, "MP3 comment");
30 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.firstGenre, "Acid Punk");
31 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.track, 6);
32 | assert.strictEqual(Mp3_id3v1_fileTests.file.tag.year, 1234);
33 | }
34 |
35 | @test
36 | public writeStandardPictures() {
37 | const tmpFilePath = TestConstants.getTempFilePath(Mp3_id3v1_fileTests.tmpFileName);
38 | StandardFileTests.writeStandardPictures(Mp3_id3v1_fileTests.sampleFilePath, tmpFilePath, ReadStyle.None);
39 | }
40 |
41 | @test
42 | public writeStandardTags() {
43 | const tmpFilePath = TestConstants.getTempFilePath(Mp3_id3v1_fileTests.tmpFileName);
44 | StandardFileTests.writeStandardTags(Mp3_id3v1_fileTests.sampleFilePath, tmpFilePath);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test-integration/mpeg_fileTest.ts:
--------------------------------------------------------------------------------
1 | import * as Chai from "chai";
2 | import {suite, test} from "@testdeck/mocha";
3 |
4 | import TestConstants from "./utilities/testConstants";
5 | import {File, ReadStyle} from "../src";
6 | import {StandardFileTests, TestTagLevel} from "./utilities/standardFileTests";
7 |
8 | const assert = Chai.assert;
9 |
10 | @suite class Mpeg_FileTests {
11 | private static readonly corruptFilePath = TestConstants.getCorruptFilePath("corrupt.mpg");
12 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample.mpg");
13 | private static readonly tmpFileName = "tmpwrite.mpg";
14 |
15 | private static file: File;
16 |
17 | public static before() {
18 | Mpeg_FileTests.file = File.createFromPath(Mpeg_FileTests.sampleFilePath);
19 | }
20 |
21 | public static after() {
22 | Mpeg_FileTests.file.dispose();
23 | }
24 |
25 | @test
26 | public readAudioProperties() {
27 | assert.strictEqual(Mpeg_FileTests.file.properties.audioBitrate, 128);
28 | assert.strictEqual(Mpeg_FileTests.file.properties.audioChannels, 2);
29 | assert.strictEqual(Mpeg_FileTests.file.properties.audioSampleRate, 44100);
30 | assert.approximately(Mpeg_FileTests.file.properties.durationMilliseconds, 1391, 0.5);
31 | assert.strictEqual(Mpeg_FileTests.file.properties.videoHeight, 480);
32 | assert.strictEqual(Mpeg_FileTests.file.properties.videoWidth, 640);
33 | }
34 |
35 | @test
36 | public readTags() {
37 | assert.isTrue(Mpeg_FileTests.file.tag.isEmpty);
38 | }
39 |
40 | @test
41 | public RemoveStandardTags() {
42 | const tempFilePath = TestConstants.getTempFilePath(Mpeg_FileTests.tmpFileName);
43 | StandardFileTests.removeStandardTags(Mpeg_FileTests.sampleFilePath, tempFilePath);
44 | }
45 |
46 | @test
47 | public TestCorruptionResistance() {
48 | StandardFileTests.testCorruptionResistance(Mpeg_FileTests.corruptFilePath);
49 | }
50 |
51 | @test
52 | public WriteStandardPictures() {
53 | const tempFilePath = TestConstants.getTempFilePath(Mpeg_FileTests.tmpFileName);
54 | StandardFileTests.writeStandardPictures(Mpeg_FileTests.sampleFilePath, tempFilePath, ReadStyle.None);
55 | }
56 |
57 | // @test
58 | // public WriteStandardPicturesLazy() {
59 | // StandardFileTests.writeStandardPictures(
60 | // Mpeg_FileTests.sampleFilePath,
61 | // Mpeg_FileTests.tmpFileName,
62 | // ReadStyle.PictureLazy
63 | // );
64 | // }
65 |
66 | @test
67 | public WriteStandardTags() {
68 | const tempFilePath = TestConstants.getTempFilePath(Mpeg_FileTests.tmpFileName);
69 | StandardFileTests.writeStandardTags(Mpeg_FileTests.sampleFilePath, tempFilePath, TestTagLevel.Medium);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/test-integration/ogg_opus_fileTests.ts:
--------------------------------------------------------------------------------
1 | import {assert} from "chai";
2 | import {suite, test} from "@testdeck/mocha";
3 |
4 | import ExtendedFileTests from "./utilities/extendedFileTests";
5 | import TestConstants from "./utilities/testConstants";
6 | import {File} from "../src";
7 | import {StandardFileTests, TestTagLevel} from "./utilities/standardFileTests";
8 |
9 | @suite class Ogg_Opus_FileTests {
10 | private static readonly sampleFilePath = TestConstants.getSampleFilePath("sample.opus");
11 | private static readonly tmpFileName = "tmpwrite.opus";
12 |
13 | private static file: File;
14 |
15 | public static before() {
16 | Ogg_Opus_FileTests.file = File.createFromPath(Ogg_Opus_FileTests.sampleFilePath);
17 | }
18 |
19 | public static after() {
20 | if (Ogg_Opus_FileTests.file) { Ogg_Opus_FileTests.file.dispose(); }
21 | }
22 |
23 | @test
24 | public readAudioProperties() {
25 | assert.strictEqual(Ogg_Opus_FileTests.file.properties.audioBitrate, 0);
26 | assert.strictEqual(Ogg_Opus_FileTests.file.properties.audioChannels, 2);
27 | assert.strictEqual(Ogg_Opus_FileTests.file.properties.audioSampleRate, 44100);
28 | assert.strictEqual(Ogg_Opus_FileTests.file.properties.bitsPerSample, 0);
29 | assert.approximately(Ogg_Opus_FileTests.file.properties.durationMilliseconds, 5232, 10);
30 | // TODO: Figure out why we're off by around 10
31 | }
32 |
33 | @test
34 | public readTags() {
35 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.album, "Opus album");
36 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.firstPerformer, "Opus artist");
37 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.description, "Opus comment");
38 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.firstGenre, "Acid Punk");
39 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.title, "Opus title");
40 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.track, 6);
41 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.trackCount, 7);
42 | assert.strictEqual(Ogg_Opus_FileTests.file.tag.year, 1234);
43 | }
44 |
45 | @test
46 | public writeStandardTags() {
47 | const tmpFilePath = TestConstants.getTempFilePath(Ogg_Opus_FileTests.tmpFileName);
48 | StandardFileTests.writeStandardTags(Ogg_Opus_FileTests.sampleFilePath, tmpFilePath, TestTagLevel.Medium);
49 | }
50 |
51 | @test
52 | public writeExtendedTags() {
53 | const tmpFilePath = TestConstants.getTempFilePath(Ogg_Opus_FileTests.tmpFileName);
54 | ExtendedFileTests.writeExtendedTags(Ogg_Opus_FileTests.sampleFilePath, tmpFilePath);
55 | }
56 |
57 | @test
58 | public writeStandardPictures() {
59 | const tmpFilePath = TestConstants.getTempFilePath(Ogg_Opus_FileTests.tmpFileName);
60 | StandardFileTests.writeStandardPictures(Ogg_Opus_FileTests.sampleFilePath, tmpFilePath);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.aac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.aac
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.aif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.aif
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.avi
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.flac
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.m4a
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.mpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.mpg
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.ogg
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.wav
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corrupt.wma:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corrupt.wma
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corruptMissingFlag.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corruptMissingFlag.ogg
--------------------------------------------------------------------------------
/test-integration/resources/corruptSamples/corruptNullTitleId3v2.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/corruptSamples/corruptNullTitleId3v2.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/apple_tags.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/apple_tags.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/bgo_658920.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/bgo_658920.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/bgo_676934.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/bgo_676934.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/bgo_701689.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/bgo_701689.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.aac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.aac
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.aif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.aif
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.ape:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.ape
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.avi
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.flac
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.m4v:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.m4v
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.mkv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.mkv
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.mpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.mpg
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.ogg
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.ogv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.ogv
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.opus:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.opus
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.wav
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample.wma:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample.wma
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_gimp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_gimp.gif
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_props_cbr.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_props_cbr.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_props_vbri.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_props_vbri.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_props_xingabr.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_props_xingabr.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_props_xingcbr.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_props_xingcbr.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_props_xingvbr.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_props_xingvbr.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_replaygain.m4a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_replaygain.m4a
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_replaygain.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_replaygain.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_teenytiny.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_teenytiny.gif
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_v1_only.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_v1_only.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_v2_3_ext_header.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_v2_3_ext_header.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_v2_4_unsynch.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_v2_4_unsynch.mp3
--------------------------------------------------------------------------------
/test-integration/resources/samples/sample_v2_only.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/benrr101/node-taglib-sharp/e92ed7210da05fa13d01947243478adce87f578c/test-integration/resources/samples/sample_v2_only.mp3
--------------------------------------------------------------------------------
/test-integration/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "experimentalDecorators": true,
5 | "inlineSources": true,
6 | "module": "commonjs",
7 | "noImplicitAny": true,
8 | "outDir": "./dist",
9 | "sourceMap": true,
10 | "baseUrl": ".",
11 | "paths": {
12 | "*": ["node_modules/*"]
13 | },
14 | "target": "es6"
15 | },
16 | "include": [ "./**/*" ]
17 | }
18 |
--------------------------------------------------------------------------------
/test-integration/utilities/extendedFileTests.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "fs";
2 | import {assert} from "chai";
3 |
4 | import Utilities from "./utilities";
5 | import {File, Tag} from "../../src";
6 |
7 | export default class ExtendedFileTests {
8 | public static writeExtendedTags(sampleFile: string, tmpFile: string): void {
9 | if (fs.existsSync(tmpFile)) {
10 | fs.unlinkSync(tmpFile);
11 | }
12 |
13 | fs.copyFileSync(sampleFile, tmpFile);
14 |
15 | try {
16 | let tmp = File.createFromPath(tmpFile);
17 | ExtendedFileTests.setTags(tmp.tag);
18 | tmp.save();
19 |
20 | tmp = File.createFromPath(tmpFile);
21 | ExtendedFileTests.checkTags(tmp.tag);
22 | } finally {
23 | Utilities.deleteBestEffort(tmpFile);
24 | }
25 | }
26 |
27 | private static checkTags(tag: Tag): void {
28 | assert.strictEqual(tag.replayGainTrackGain, -10.28);
29 | assert.strictEqual(tag.replayGainTrackPeak, 0.999969);
30 | assert.strictEqual(tag.replayGainAlbumGain, -9.98);
31 | assert.strictEqual(tag.replayGainAlbumPeak, 0.999980);
32 | }
33 |
34 | private static setTags(tag: Tag): void {
35 | tag.replayGainTrackGain = -10.28;
36 | tag.replayGainTrackPeak = 0.999969;
37 | tag.replayGainAlbumGain = -9.98;
38 | tag.replayGainAlbumPeak = 0.999980;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/test-integration/utilities/testConstants.ts:
--------------------------------------------------------------------------------
1 | import * as Path from "path";
2 | import {v4 as Uuidv4} from "uuid";
3 |
4 | export default class TestConstants {
5 | public static testFileFolderPath: string = "./test-integration/resources";
6 |
7 | public static getCorruptFilePath: (fileName: string) => string = (fileName: string ) => {
8 | return Path.join(TestConstants.testFileFolderPath, "corruptSamples", fileName);
9 | }
10 |
11 | public static getSampleFilePath: (fileName: string) => string = (fileName: string) => {
12 | return Path.join(TestConstants.testFileFolderPath, "samples", fileName);
13 | }
14 |
15 | public static getTempFilePath: (fileName: string) => string = (fileName: string) => {
16 | const fileUid: string = Uuidv4();
17 | return Path.join(TestConstants.testFileFolderPath, `${fileUid}_${fileName}`);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test-integration/utilities/utilities.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "fs";
2 |
3 | export default class Utilities {
4 | public static deleteBestEffort(path: string) {
5 | try {
6 | fs.unlinkSync(path);
7 | } catch {
8 | // Ignore failed deletions
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test-unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": ["../.eslintrc.js"],
3 | "rules": {
4 | "@typescript-eslint/dot-notation": "off",
5 | "@typescript-eslint/explicit-function-return-type": "off",
6 | "@typescript-eslint/naming-convention": "off",
7 | "@typescript-eslint/no-unsafe-argument": "off",
8 | "@typescript-eslint/no-unsafe-member-access": "off",
9 | "@typescript-eslint/no-unused-vars": "off",
10 | "dot-notation": "off"
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/test-unit/asf/objectTests.ts:
--------------------------------------------------------------------------------
1 | import {test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import TestFile from "../utilities/testFile";
5 | import UuidWrapper from "../../src/uuidWrapper";
6 | import {ByteVector} from "../../src/byteVector";
7 | import {Testers} from "../utilities/testers";
8 | import {File} from "../../src/file";
9 |
10 | export default abstract class ObjectTests {
11 | protected abstract get fromFileConstructor(): (f: File, p: number) => TObject;
12 | protected abstract get minSize(): number;
13 | protected abstract get objectGuid(): UuidWrapper;
14 |
15 | @test
16 | public fromFile_invalidParameters() {
17 | // Arrange
18 | const mockFile = {};
19 |
20 | // Act / Assert
21 | Testers.testTruthy((v: File) => this.fromFileConstructor(v, 0));
22 | Testers.testSafeUint((v) => this.fromFileConstructor(mockFile, v));
23 | }
24 |
25 | @test
26 | public fromFile_tooSmall() {
27 | // Only run if there is a min size
28 | if (this.minSize === undefined) {
29 | return;
30 | }
31 |
32 | // Arrange
33 | const data = ByteVector.concatenate(
34 | ByteVector.fromSize(10), // Offset
35 | this.objectGuid.toBytes(), // Object ID
36 | ByteVector.fromUlong(Math.min(26, this.minSize - 10)) // Object size
37 | );
38 | const file = TestFile.getFile(data);
39 |
40 | // Act / Assert
41 | assert.throws(() => this.fromFileConstructor(file, 10));
42 | }
43 |
44 | @test
45 | public fromFile_wrongGuid() {
46 | // Only run if there is a guid
47 | if (this.objectGuid === undefined) {
48 | return;
49 | }
50 |
51 | // Arrange
52 | const data = ByteVector.concatenate(
53 | ByteVector.fromSize(10), // Offset
54 | new UuidWrapper().toBytes(), // Object ID
55 | ByteVector.fromUlong(123), // Object size
56 | ByteVector.fromSize(20) // Just some bogus bytes
57 | );
58 | const file = TestFile.getFile(data);
59 |
60 | // Act / Assert
61 | assert.throws(() => this.fromFileConstructor(file, 10));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/test-unit/fileAbstractionTests.ts:
--------------------------------------------------------------------------------
1 | import * as Chai from "chai";
2 | import * as TypeMoq from "typemoq";
3 | import {suite, test} from "@testdeck/mocha";
4 |
5 | import TestConstants from "./testConstants";
6 | import {LocalFileAbstraction} from "../src/fileAbstraction";
7 | import {IStream} from "../src/stream";
8 | import {Testers} from "./utilities/testers";
9 |
10 | // Setup Chai
11 | const assert = Chai.assert;
12 |
13 | @suite class LocalFileAbstractionTests {
14 | @test
15 | public constructor_test() {
16 | // Act
17 | const fileAbstraction = new LocalFileAbstraction(TestConstants.testFilePath);
18 |
19 | // Assert
20 | assert.strictEqual(fileAbstraction.name, TestConstants.testFilePath);
21 |
22 | let readStream;
23 | let writeStream;
24 | try {
25 | readStream = fileAbstraction.readStream;
26 | assert.isFalse(readStream.canWrite);
27 |
28 | writeStream = fileAbstraction.writeStream;
29 | assert.isTrue(writeStream.canWrite);
30 | } finally {
31 | if (readStream) { readStream.close(); }
32 | if (writeStream) { writeStream.close(); }
33 | }
34 | }
35 |
36 | @test
37 | public closeStream_invalidStream() {
38 | // Arrange
39 | const abstraction = new LocalFileAbstraction(TestConstants.testFilePath);
40 |
41 | // Act / Assert
42 | Testers.testTruthy((v: IStream) => { abstraction.closeStream(v); });
43 | }
44 |
45 | @test
46 | public closeStream_closesStream() {
47 | // Arrange
48 | const abstraction = new LocalFileAbstraction(TestConstants.testFilePath);
49 | const testStream = TypeMoq.Mock.ofType();
50 | testStream.setup((s) => s.close());
51 |
52 | // Act
53 | abstraction.closeStream(testStream.object);
54 |
55 | // Assert
56 | testStream.verify((s) => s.close(), TypeMoq.Times.once());
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/test-unit/id3v2/frameConstructorTests.ts:
--------------------------------------------------------------------------------
1 | import {test} from "@testdeck/mocha";
2 |
3 | import {ByteVector} from "../../src/byteVector";
4 | import {Frame} from "../../src/id3v2/frames/frame";
5 | import {Id3v2FrameHeader} from "../../src/id3v2/frames/frameHeader";
6 | import {FrameIdentifiers} from "../../src/id3v2/frameIdentifiers";
7 | import {Testers} from "../utilities/testers";
8 |
9 | export default abstract class FrameConstructorTests {
10 |
11 | public abstract get fromOffsetRawData(): (d: ByteVector, o: number, h: Id3v2FrameHeader, v: number) => Frame;
12 | public abstract get fromRawData(): (d: ByteVector, v: number) => Frame;
13 |
14 | @test
15 | public fromOffsetRawData_falsyData_throws() {
16 | // Arrange
17 | const header = new Id3v2FrameHeader(FrameIdentifiers.WCOM);
18 |
19 | // Act/Assert
20 | Testers.testTruthy((v: ByteVector) => { this.fromOffsetRawData(v, 2, header, 4); });
21 | }
22 |
23 | @test
24 | public fromOffsetRawData_invalidVersion_throws() {
25 | // Arrange
26 | const data = ByteVector.empty();
27 | const header = new Id3v2FrameHeader(FrameIdentifiers.WCOM);
28 |
29 | // Act/Assert
30 | Testers.testUint((v: number) => { this.fromOffsetRawData(data, v, header, 4); });
31 | }
32 |
33 | @test
34 | public fromOffsetRawData_falsyHeader_throws() {
35 | // Arrange
36 | const data = ByteVector.empty();
37 |
38 | // Act/Assert
39 | Testers.testTruthy((v: Id3v2FrameHeader) => { this.fromOffsetRawData(data, 2, v, 4); });
40 | }
41 |
42 | @test
43 | public fromRawData_falsyData_throws() {
44 | // Act/Assert
45 | Testers.testTruthy((v: ByteVector) => { this.fromRawData(v, 2); });
46 | }
47 |
48 | @test
49 | public fromRawData_invalidVersion_throws() {
50 | // Arrange
51 | const data = ByteVector.empty();
52 |
53 | // Act/Assert
54 | Testers.testByte((v: number) => { this.fromRawData(data, v); });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/test-unit/id3v2/tagExtendedHeaderTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import Id3v2ExtendedHeader from "../../src/id3v2/id3v2ExtendedHeader";
5 | import {ByteVector} from "../../src/byteVector";
6 | import {Testers} from "../utilities/testers";
7 |
8 | @suite class Id3v2_TagExtendedHeaderTests {
9 | @test
10 | public fromData_falsyData() {
11 | // Act/Assert
12 | Testers.testTruthy((v: ByteVector) => { Id3v2ExtendedHeader.fromData(v, 2); });
13 | }
14 |
15 | @test
16 | public fromData_invalidVersion() {
17 | // Arrange
18 | const testData = ByteVector.empty();
19 |
20 | // Act/Assert
21 | Testers.testByte((v: number) => { Id3v2ExtendedHeader.fromData(testData, v); });
22 | }
23 |
24 | @test
25 | public fromData_version3() {
26 | // Arrange
27 | const testData = ByteVector.concatenate(0x10, 0x10, 0x10, 0x10);
28 |
29 | // Act
30 | const output = Id3v2ExtendedHeader.fromData(testData, 3);
31 |
32 | // Assert
33 | assert.equal(output.size, 4 + 0x2040810);
34 | }
35 |
36 | @test
37 | public fromData_version2() {
38 | // Arrange
39 | const testData = ByteVector.concatenate(0x10, 0x10, 0x10, 0x10);
40 |
41 | // Act
42 | const output = Id3v2ExtendedHeader.fromData(testData, 2);
43 |
44 | // Assert
45 | assert.equal(output.size, 0x2040810);
46 | }
47 |
48 | @test
49 | public fromData_version4() {
50 | // Arrange
51 | const testData = ByteVector.concatenate(0x10, 0x10, 0x10, 0x10);
52 |
53 | // Act
54 | const output = Id3v2ExtendedHeader.fromData(testData, 4);
55 |
56 | // Assert
57 | assert.equal(output.size, 0x2040810);
58 | }
59 |
60 | public fromEmpty() {
61 | // Act
62 | const output = Id3v2ExtendedHeader.fromEmpty();
63 |
64 | // Assert
65 | assert.equal(output.size, 0);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/test-unit/matroska/matroskaTagTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 | import {Mock} from "typemoq";
4 |
5 | import MatroskaTag from "../../src/matroska/matroskaTag";
6 | import MatroskaTagValue from "../../src/matroska/matroskaTagValue";
7 | import {MatroskaTagTarget} from "../../src/matroska/matroskaTagTarget";
8 | import {Testers} from "../utilities/testers";
9 |
10 | @suite
11 | class Matroska_TagTests {
12 | @test
13 | public constructor_invalidParams() {
14 | // Arrange
15 | const mockValue = Mock.ofType();
16 | const mockTarget = Mock.ofType();
17 |
18 | // Act / Assert
19 | Testers.testTruthy((v) => new MatroskaTag(v, mockTarget.object));
20 | Testers.testTruthy((v) => new MatroskaTag(mockValue.object, v));
21 | }
22 |
23 | @test
24 | public constructor_valid() {
25 | // Arrange
26 | const mockValue = Mock.ofType();
27 | const mockTarget = Mock.ofType();
28 |
29 | // Act
30 | const tag = new MatroskaTag(mockValue.object, mockTarget.object);
31 |
32 | // Assert
33 | assert.strictEqual(tag.value, mockValue.object);
34 | assert.strictEqual(tag.target, mockTarget.object);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/test-unit/matroska/utils.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector, StringType} from "../../src";
2 | import EbmlElement from "../../src/ebml/ebmlElement";
3 | import TestFile from "../utilities/testFile";
4 |
5 | export default class MatroskaTestUtils {
6 | public static getTestElement(value: string|boolean|number|bigint|ByteVector, id: number): EbmlElement {
7 | let bytes: ByteVector;
8 | // noinspection FallThroughInSwitchStatementJS
9 | switch (typeof (value)) {
10 | case "object":
11 | if (value instanceof ByteVector) {
12 | bytes = value;
13 | }
14 | break;
15 |
16 | case "string":
17 | bytes = ByteVector.fromString(value, StringType.UTF8);
18 | break;
19 |
20 | case "bigint":
21 | bytes = ByteVector.fromUlong(value);
22 | break;
23 |
24 | case "boolean":
25 | value = value ? 1 : 0;
26 |
27 | case "number":
28 | bytes = ByteVector.fromUint(value);
29 | break;
30 | }
31 |
32 | return new EbmlElement(TestFile.getFile(bytes), 0, id, bytes.length, {});
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/test-unit/mpeg/mpegContainerFileTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import MpegContainerFile from "../../src/mpeg/mpegContainerFile";
5 | import MpegContainerFileSettings from "../../src/mpeg/mpegContainerFileSettings";
6 | import {default as TestFile} from "../utilities/testFile";
7 | import {ByteVector} from "../../src/byteVector";
8 | import {ReadStyle} from "../../src/file";
9 | import {TagTypes} from "../../src/tag";
10 |
11 | @suite class MpegContainer_MpegContainerFileTests {
12 | @test
13 | public constructor_noDefaultsPreferred() {
14 | // Arrange
15 | const originalDefaults = MpegContainerFileSettings.defaultTagTypes;
16 | try {
17 | const testAbstraction = TestFile.getFileAbstraction(ByteVector.fromSize(100));
18 |
19 | // Act
20 | MpegContainerFileSettings.defaultTagTypes = TagTypes.None;
21 | const file = new MpegContainerFile(testAbstraction, ReadStyle.None);
22 |
23 | // Assert
24 | assert.isEmpty(file.tag.tags);
25 | assert.strictEqual(file.tagTypes, TagTypes.None);
26 | assert.strictEqual(file.tagTypesOnDisk, TagTypes.None);
27 | assert.isUndefined(file.properties);
28 |
29 | } finally {
30 | // Cleanup
31 | MpegContainerFileSettings.defaultTagTypes = originalDefaults;
32 | }
33 | }
34 |
35 | @test
36 | public constructor_defaultTagsAtEnd() {
37 | // Arrange
38 | const originalDefaults = MpegContainerFileSettings.defaultTagTypes;
39 | try {
40 | const testAbstraction = TestFile.getFileAbstraction(ByteVector.fromSize(100));
41 |
42 | // Act
43 | MpegContainerFileSettings.defaultTagTypes = TagTypes.Id3v1 | TagTypes.Id3v2 | TagTypes.Ape;
44 | const file = new MpegContainerFile(testAbstraction, ReadStyle.None);
45 |
46 | // Assert
47 | assert.strictEqual(file.tag.tags.length, 3);
48 | assert.strictEqual(file.tagTypes, TagTypes.Id3v1 | TagTypes.Id3v2 | TagTypes.Ape);
49 | assert.strictEqual(file.tagTypesOnDisk, TagTypes.None);
50 |
51 | assert.strictEqual(file.tag.startTag.tags.length, 0);
52 | assert.strictEqual(file.tag.startTag.tagTypes, TagTypes.None);
53 | assert.strictEqual(file.tag.endTag.tags.length, 3);
54 | assert.strictEqual(file.tag.endTag.tagTypes, TagTypes.Id3v1 | TagTypes.Id3v2 | TagTypes.Ape);
55 |
56 | assert.isUndefined(file.properties);
57 |
58 | } finally {
59 | // Cleanup
60 | MpegContainerFileSettings.defaultTagTypes = originalDefaults;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/test-unit/mpeg/mpegVideoHeaderTests.ts:
--------------------------------------------------------------------------------
1 | import * as TypeMoq from "typemoq";
2 | import {suite, test} from "@testdeck/mocha";
3 | import {assert} from "chai";
4 |
5 | import MpegVideoHeader from "../../src/mpeg/mpegVideoHeader";
6 | import TestFile from "../utilities/testFile";
7 | import {ByteVector} from "../../src/byteVector";
8 | import {File} from "../../src/file";
9 | import {MediaTypes} from "../../src/properties";
10 | import {Testers} from "../utilities/testers";
11 |
12 | @suite class Mpeg_VideoHeader_ConstructorTests {
13 | @test
14 | public constructor_invalidArguments() {
15 | // Act/Assert
16 | Testers.testTruthy((f: File) => new MpegVideoHeader(f, 0));
17 | Testers.testUint((p: number) => new MpegVideoHeader(TypeMoq.Mock.ofType().object, p));
18 | }
19 |
20 | @test
21 | public constructor_headerTooShort() {
22 | // Arrange
23 | const mockData = ByteVector.fromSize(10);
24 | const mockFile = TestFile.getFile(mockData);
25 |
26 | // Act/Assert
27 | assert.throws(() => new MpegVideoHeader(mockFile, 5));
28 | }
29 |
30 | @test
31 | public constructor_validData() {
32 | // Arrange
33 | const mockData = ByteVector.concatenate(
34 | 0x00, 0x00, 0x00,
35 | 0x28, 0x31, 0xE3, 0x26, // 643x483, 4:3 aspect ratio, 50fps
36 | 0xD8, 0x53, 0xBF // 221518bps
37 | );
38 | const mockFile = TestFile.getFile(mockData);
39 |
40 | // Act
41 | const header = new MpegVideoHeader(mockFile, 3);
42 |
43 | // Assert
44 | assert.strictEqual(header.description, "MPEG Video");
45 | assert.strictEqual(header.durationMilliseconds, 0);
46 | assert.strictEqual(header.mediaTypes, MediaTypes.Video);
47 | assert.strictEqual(header.videoBitrate, 221518);
48 | assert.strictEqual(header.videoFrameRate, 50);
49 | assert.strictEqual(header.videoHeight, 483);
50 | assert.strictEqual(header.videoWidth, 643);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/test-unit/mpeg/vbriHeaderTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 | import {Mock} from "typemoq";
4 |
5 | import TestFile from "../utilities/testFile";
6 | import VbriHeader from "../../src/mpeg/vbriHeader";
7 | import {ByteVector, StringType} from "../../src/byteVector";
8 | import {File} from "../../src/file";
9 | import {Testers} from "../utilities/testers";
10 |
11 | @suite class Mpeg_XingHeaderTests {
12 |
13 | @test
14 | public fromFile_invalidParameters() {
15 | // Arrange
16 | const mockFile = Mock.ofType().object;
17 |
18 | // Act / Assert
19 | Testers.testTruthy((f: File) => VbriHeader.fromFile(f, 0, 1, 1, ));
20 | Testers.testUint((v: number) => VbriHeader.fromFile(mockFile, v, 1, 1));
21 | Testers.testUint((v: number) => VbriHeader.fromFile(mockFile, 0, v, 1));
22 | assert.throws(() => VbriHeader.fromFile(mockFile, 0, 0, 1));
23 | Testers.testUint((v: number) => VbriHeader.fromFile(mockFile, 0, 1, v));
24 | assert.throws(() => VbriHeader.fromFile(mockFile, 0, 1, 0));
25 | }
26 |
27 | @test
28 | public fromFile_fileTooShort() {
29 | // Arrange
30 | const file = TestFile.getFile(ByteVector.fromSize(60));
31 |
32 | // Act / Assert
33 | assert.isUndefined(VbriHeader.fromFile(file, 1, 1, 1));
34 | }
35 |
36 | @test
37 | public fromFile_doesNotStartWithIdentifier() {
38 | // Arrange
39 | const file = TestFile.getFile(ByteVector.fromSize(60));
40 |
41 | // Act / Assert
42 | assert.isUndefined(VbriHeader.fromFile(file, 0, 1, 1));
43 | }
44 |
45 | @test
46 | public fromFile_validParameters() {
47 | // Arrange
48 | const file = TestFile.getFile(ByteVector.concatenate(
49 | ByteVector.fromSize(40),
50 | ByteVector.fromString("VBRI", StringType.Latin1),
51 | ByteVector.fromSize(2), // Version
52 | ByteVector.fromUshort(12), // Delay
53 | ByteVector.fromSize(2), // Quality
54 | ByteVector.fromUint(12345), // Bytes
55 | ByteVector.fromUint(123), // Frames
56 | ByteVector.fromSize(8) // TOC Size, TOC scale, TOC entry size, TOC entry frame count
57 | ));
58 |
59 | // Act
60 | const header = VbriHeader.fromFile(file, 4, 1152, 44100);
61 |
62 | // Assert
63 | assert.isOk(header);
64 | assert.strictEqual(header.bitrateKilobytes, 30);
65 | assert.approximately(header.durationMilliseconds, 3212, 1);
66 | assert.strictEqual(header.totalBytes, 12345);
67 | assert.strictEqual(header.totalFrames, 123);
68 | }
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/test-unit/mpeg4/mpeg4UtilsTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import Mpeg4BoxHeader from "../../src/mpeg4/mpeg4BoxHeader";
5 | import Mpeg4Utils from "../../src/mpeg4/mpeg4Utils";
6 | import {ByteVector, StringType} from "../../src/byteVector";
7 |
8 | @suite
9 | class Mpeg4_Mpeg4UtilsTests {
10 | @test
11 | public addParent_withParentsNull_returnsListContainingOnlyCurrent() {
12 | // Arrange
13 | const current: Mpeg4BoxHeader = Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.Latin1));
14 |
15 | // Act
16 | const headers: Mpeg4BoxHeader[] = Mpeg4Utils.addParent(null, current);
17 |
18 | // Assert
19 | assert.equal(headers.length, 1);
20 | assert.equal(headers[0], current);
21 | }
22 |
23 | @test
24 | public addParent_withParentsUndefined_returnsListContainingOnlyCurrent() {
25 | // Arrange
26 | const current: Mpeg4BoxHeader = Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.Latin1));
27 |
28 | // Act
29 | const headers: Mpeg4BoxHeader[] = Mpeg4Utils.addParent(undefined, current);
30 |
31 | // Assert
32 | assert.equal(headers.length, 1);
33 | assert.equal(headers[0], current);
34 | }
35 |
36 | @test
37 | public addParent_withParentsHaving2Elements_returnsListContainingParentsFollowedByCurrent() {
38 | // Arrange
39 | const parent1: Mpeg4BoxHeader = Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.Latin1));
40 | const parent2: Mpeg4BoxHeader = Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.Latin1));
41 | const parents: Mpeg4BoxHeader[] = [parent1, parent2];
42 | const current: Mpeg4BoxHeader = Mpeg4BoxHeader.fromType(ByteVector.fromString("xxxx", StringType.Latin1));
43 |
44 | // Act
45 | const headers: Mpeg4BoxHeader[] = Mpeg4Utils.addParent(parents, current);
46 |
47 | // Assert
48 | assert.equal(headers.length, 3);
49 | assert.equal(headers[0], parent1);
50 | assert.equal(headers[1], parent2);
51 | assert.equal(headers[2], current);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test-unit/ogg/codecPackets.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector, StringType} from "../../src/byteVector";
2 |
3 | export default class CodecPackets {
4 | public static getTestOpusPacket(): ByteVector {
5 | return ByteVector.concatenate(
6 | ByteVector.fromString("OpusHead", StringType.UTF8),
7 | 0x01, 0x08, 0x03, 0x04,
8 | 0x05, 0x06, 0x07, 0x08,
9 | 0x09, 0x0A, 0x01, 0x05, 0x03
10 | );
11 | }
12 |
13 | public static getTestTheoraPacket(): ByteVector {
14 | return ByteVector.concatenate(
15 | 0x80, ByteVector.fromString("theora", StringType.UTF8),
16 | 0x01, 0x02, 0x03, // version
17 | ByteVector.fromUint(0), // Size in macro blocks
18 | 0xF0, 0x12, 0x34, // Width in pixels
19 | 0xF0, 0x45, 0x67, // Height in pixels
20 | 0x01, 0x02, // Picture offset in pixels
21 | ByteVector.fromUint(1234), // Frame rate numerator
22 | ByteVector.fromUint(2345), // Frame rate denominator
23 | ByteVector.fromSize(10, 0xFF), // Stuff we don't care about
24 | 0xFC, 0x56, 0xEF // "last bits" including keyframe granule shift
25 | );
26 | }
27 |
28 | public static getTestVorbisPacket(): ByteVector {
29 | return ByteVector.concatenate(
30 | 0x01, ByteVector.fromString("vorbis", StringType.UTF8),
31 | ByteVector.fromUint(1234, false), // Version
32 | 0x05, // Channels
33 | ByteVector.fromUint(456789, false), // Sample rate
34 | ByteVector.fromUint(200000, false), // bitrate max
35 | ByteVector.fromUint(128000, false), // bitrate nominal
36 | ByteVector.fromUint(100000, false), // bitrate min
37 | // We don't care about anything after this
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/test-unit/resources/testFile.txt:
--------------------------------------------------------------------------------
1 | 12345abcde
--------------------------------------------------------------------------------
/test-unit/riff/riffWaveFormatExTests.ts:
--------------------------------------------------------------------------------
1 | import {suite, test} from "@testdeck/mocha";
2 | import {assert} from "chai";
3 |
4 | import RiffWaveFormatEx from "../../src/riff/riffWaveFormatEx";
5 | import {default as Resources} from "./resources";
6 | import {ByteVector} from "../../src/byteVector";
7 | import {MediaTypes} from "../../src/properties";
8 | import {Testers} from "../utilities/testers";
9 |
10 | @suite class Riff_WaveFormatExTests {
11 | @test
12 | public constructor_invalidParams() {
13 | // Act / Assert
14 | Testers.testTruthy((v: ByteVector) => new RiffWaveFormatEx(v));
15 | }
16 |
17 | @test
18 | public constructor_dataTooShort() {
19 | // Arrange
20 | const data = ByteVector.fromSize(10);
21 |
22 | // Act / Assert
23 | assert.throws(() => new RiffWaveFormatEx(data));
24 | }
25 |
26 | @test
27 | public constructor_knownAudioFormat() {
28 | // Arrange
29 | const data = Resources.getAudioFormatBlock(0xF1AC);
30 |
31 | // Act
32 | const object = new RiffWaveFormatEx(data);
33 |
34 | // Assert
35 | assert.strictEqual(object.audioBitrate, 2345 * 8 / 1000);
36 | assert.strictEqual(object.audioChannels, 3);
37 | assert.strictEqual(object.audioSampleRate, 1234);
38 | assert.strictEqual(object.averageBytesPerSecond, 2345);
39 | assert.strictEqual(object.bitsPerSample, 16);
40 | assert.isTrue(object.description.indexOf("FLAC") >= 0);
41 | assert.isTrue(object.description.indexOf("0xF1AC") >= 0);
42 | assert.strictEqual(object.durationMilliseconds, 0);
43 | assert.strictEqual(object.formatTag, 0xF1AC);
44 | assert.strictEqual(object.mediaTypes, MediaTypes.LosslessAudio);
45 | }
46 |
47 | @test
48 | public constructor_unknownAudioFormat() {
49 | // Arrange
50 | const data = Resources.getAudioFormatBlock(0xBBBB);
51 |
52 | // Act
53 | const object = new RiffWaveFormatEx(data);
54 |
55 | // Assert
56 | assert.strictEqual(object.audioBitrate, 2345 * 8 / 1000);
57 | assert.strictEqual(object.audioChannels, 3);
58 | assert.strictEqual(object.audioSampleRate, 1234);
59 | assert.strictEqual(object.averageBytesPerSecond, 2345);
60 | assert.strictEqual(object.bitsPerSample, 16);
61 | assert.isTrue(object.description.indexOf( "Unknown") >= 0);
62 | assert.isTrue(object.description.indexOf("0xBBBB") >= 0);
63 | assert.strictEqual(object.durationMilliseconds, 0);
64 | assert.strictEqual(object.formatTag, 0xBBBB);
65 | assert.strictEqual(object.mediaTypes, MediaTypes.LosslessAudio);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/test-unit/testConstants.ts:
--------------------------------------------------------------------------------
1 | import * as Path from "path";
2 | import {v4 as Uuidv4} from "uuid";
3 |
4 | import {ByteVector, StringType} from "../src/byteVector";
5 |
6 | export default class TestConstants {
7 | public static testFileFolderPath: string = "./test-unit/resources/";
8 | public static testFileName = "testFile.txt";
9 | public static testFilePath: string = Path.join(TestConstants.testFileFolderPath, TestConstants.testFileName);
10 | public static testFileContents: Uint8Array = new Uint8Array(
11 | [0x31, 0x32, 0x33, 0x34, 0x35, 0x61, 0x62, 0x63, 0x64, 0x65]
12 | );
13 | public static testFileContentsStr: string = "12345abcde";
14 |
15 | public static getTestFilePath: () => string = () => {
16 | const fileUid: string = Uuidv4();
17 | return Path.join(TestConstants.testFileFolderPath, `testFile_${fileUid}.txt`);
18 | }
19 |
20 | public static testStrings: {[key: string]: {bytes: Uint8Array, str: string}} = {
21 | Latin1: {
22 | bytes: new Uint8Array([
23 | 0x21, 0x31, 0x32, 0x33, 0x41, 0x42, 0x43, 0x61, 0x62, 0x63, 0xC1, 0xD1, 0xFC, 0xAE, 0xBE
24 | ]),
25 | str: "!123ABCabcÁÑü®¾"
26 | },
27 | UTF16BE: {
28 | bytes: new Uint8Array([
29 | 0x00, 0x61, 0x00, 0x62, 0x00, 0x63,
30 | 0x03, 0xBA, 0x03, 0xCC, 0x03, 0xC3, 0x03, 0xBC, 0x03, 0xB5
31 | ]),
32 | str: "abcκόσμε"
33 | },
34 | UTF16LE: {
35 | bytes: new Uint8Array([
36 | 0x61, 0x00, 0x62, 0x00, 0x63, 0x00,
37 | 0xBA, 0x03, 0xCC, 0x03, 0xC3, 0x03, 0xBC, 0x03, 0xB5, 0x03
38 | ]),
39 | str: "abcκόσμε"
40 | },
41 | UTF16LEWithBOM: {
42 | bytes: new Uint8Array([
43 | 0xFF, 0xFE,
44 | 0x61, 0x00, 0x62, 0x00, 0x63, 0x00,
45 | 0xBA, 0x03, 0xCC, 0x03, 0xC3, 0x03, 0xBC, 0x03, 0xB5, 0x03
46 | ]),
47 | str: "abcκόσμε"
48 | },
49 | UTF8: {
50 | bytes: new Uint8Array([
51 | 0x61, 0x62, 0x63,
52 | 0xCE, 0xBA, 0xCF, 0x8C, 0xCF, 0x83, 0xCE, 0xBC, 0xCE, 0xB5
53 | ]),
54 | str: "abcκόσμε"
55 | }
56 | };
57 |
58 | public static testByteVector: ByteVector = ByteVector.fromString("foobarbaz", StringType.UTF8);
59 |
60 | public static syncedUint = 0x2040810;
61 | public static syncedUintBytes = ByteVector.fromSize(4, 0x10);
62 | }
63 |
--------------------------------------------------------------------------------
/test-unit/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "experimentalDecorators": true,
5 | "inlineSources": true,
6 | "module": "commonjs",
7 | "noImplicitAny": true,
8 | "outDir": "./dist",
9 | "sourceMap": true,
10 | "baseUrl": ".",
11 | "paths": {
12 | "*": ["node_modules/*"]
13 | },
14 | "target": "es6"
15 | },
16 | "include": [ "./**/*" ]
17 | }
18 |
--------------------------------------------------------------------------------
/test-unit/utilities/propertyTests.ts:
--------------------------------------------------------------------------------
1 | import {assert} from "chai";
2 |
3 | export default class PropertyTests {
4 | public static propertyRoundTrip(set: (v: T) => void, get: () => T, val: T) {
5 | // Act
6 | set(val);
7 | const output = get();
8 |
9 | // Assert
10 | assert.deepStrictEqual(output, val);
11 | }
12 |
13 | public static propertyNormalized(set: (v: T) => void, get: () => T, input: T, output: T) {
14 | // Act
15 | set(input);
16 | const result = get();
17 |
18 | // Assert
19 | assert.deepStrictEqual(result, output);
20 | }
21 |
22 | public static propertyThrows(set: (v: T) => void, input: T) {
23 | // Act
24 | assert.throws(() => { set(input); });
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test-unit/utilities/testFile.ts:
--------------------------------------------------------------------------------
1 | import * as TypeMoq from "typemoq";
2 |
3 | import TestConstants from "../testConstants";
4 | import TestStream from "./testStream";
5 | import {ByteVector} from "../../src/byteVector";
6 | import {File} from "../../src/file";
7 | import {IStream, SeekOrigin} from "../../src/stream";
8 | import {IFileAbstraction} from "../../src/fileAbstraction";
9 |
10 | export type TestFileAbstraction = IFileAbstraction & {allBytes: ByteVector};
11 | export default {
12 | mockFile: (): File => { return TypeMoq.Mock.ofType().object; },
13 | getFile: (data: ByteVector|number[]): File => {
14 | const mockFile = TypeMoq.Mock.ofType();
15 | let position = 0;
16 |
17 | const dataBv = data instanceof ByteVector
18 | ? data
19 | : ByteVector.fromByteArray(data);
20 |
21 | mockFile.setup((f) => f.length).returns(() => dataBv.length);
22 | mockFile.setup((f) => f.seek(TypeMoq.It.isAnyNumber(), TypeMoq.It.isAny()))
23 | .returns((p: number, o: SeekOrigin) => {
24 | switch (o || SeekOrigin.Begin) {
25 | case SeekOrigin.Begin:
26 | position = Math.min(dataBv.length, p);
27 | break;
28 | case SeekOrigin.Current:
29 | position = Math.min(dataBv.length, position + p);
30 | break;
31 | case SeekOrigin.End:
32 | position = Math.min(dataBv.length, dataBv.length + p);
33 | break;
34 | }
35 | });
36 | mockFile.setup((f) => f.readBlock(TypeMoq.It.isAnyNumber()))
37 | .returns((s: number) => {
38 | if (position + s > dataBv.length) {
39 | s = dataBv.length - position;
40 | }
41 | if (s <= 0) {
42 | return ByteVector.empty();
43 | }
44 |
45 | const output = dataBv.subarray(position, s);
46 | position += s;
47 | return output;
48 | });
49 | mockFile.setup((f) => f.position)
50 | .returns(() => {
51 | return position;
52 | });
53 | mockFile.setup((f) => f.mode);
54 |
55 | return mockFile.object;
56 | },
57 | getFileAbstraction: (data: ByteVector): TestFileAbstraction => {
58 | return {
59 | name: TestConstants.name,
60 | get allBytes(): ByteVector { return data; },
61 | get readStream(): IStream { return new TestStream(data, false); },
62 | get writeStream(): IStream { return new TestStream(data, true); },
63 | closeStream: (stream: IStream): void => { stream.close(); }
64 | };
65 | }
66 | };
67 |
--------------------------------------------------------------------------------
/test-unit/utilities/testStream.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector} from "../../src/byteVector";
2 | import {IStream, SeekOrigin} from "../../src/stream";
3 |
4 | export default class TestStream implements IStream {
5 | private readonly _isWritable: boolean;
6 | private readonly _data: ByteVector;
7 | private _position: number;
8 |
9 | public constructor(bytesToReturn: ByteVector, isWritable: boolean) {
10 | this._data = bytesToReturn;
11 | this._position = 0;
12 | this._isWritable = isWritable;
13 | }
14 |
15 | public get canWrite(): boolean {
16 | return this._isWritable;
17 | }
18 |
19 | public get data(): ByteVector { return this._data; }
20 |
21 | public get length(): number {
22 | return this._data.length;
23 | }
24 |
25 | public get position(): number {
26 | return this._position;
27 | }
28 | public set position(value: number) {
29 | this._position = value;
30 | }
31 |
32 | public close(): void { /* no op */ }
33 |
34 | public read(buffer: Uint8Array, bufferOffset: number, length: number): number {
35 | let bytesRead = 0;
36 | while (bytesRead < length && this._position + bytesRead < this._data.length) {
37 | buffer[bufferOffset + bytesRead] = this._data.get(this._position + bytesRead);
38 | bytesRead++;
39 | }
40 |
41 | this._position += bytesRead;
42 | return bytesRead;
43 | }
44 |
45 | public seek(offset: number, origin: SeekOrigin): void {
46 | switch (origin) {
47 | case SeekOrigin.Begin:
48 | this._position = offset;
49 | break;
50 | case SeekOrigin.Current:
51 | this._position += offset;
52 | break;
53 | case SeekOrigin.End:
54 | this._position = this._data.length - offset;
55 | break;
56 | }
57 | }
58 |
59 | public setLength(length: number): void {
60 | this._data.resize(length);
61 | this._position = Math.max(this.length, this._position);
62 | }
63 |
64 | public write(buffer: ByteVector | Uint8Array, bufferOffset: number, length: number): number {
65 | if (buffer instanceof Uint8Array) {
66 | buffer = ByteVector.fromByteArray(buffer);
67 | }
68 |
69 | if (!this._isWritable) {
70 | throw new Error("Invalid operation: this stream is a read-only stream");
71 | }
72 |
73 | const bufferStart = bufferOffset;
74 | const bufferEnd = bufferOffset + length;
75 | const bytesToWrite = buffer.subarray(bufferStart, bufferEnd);
76 | this._data.splice(this._position, bytesToWrite.length, bytesToWrite);
77 | this._position = bufferOffset + bytesToWrite.length;
78 |
79 | return bytesToWrite.length;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/test-unit/xiph/resources.ts:
--------------------------------------------------------------------------------
1 | import {ByteVector, PictureType, StringType} from "../../src";
2 |
3 | export default class XiphTestResources {
4 | public static readonly pictureData = ByteVector.fromString("foobarbaz", StringType.UTF8);
5 | public static readonly pictureMimeType = "application/octet-stream";
6 | public static readonly pictureDescription = "image";
7 | public static readonly pictureWidth = 640;
8 | public static readonly pictureHeight = 480;
9 | public static readonly pictureColorDepth = 123;
10 | public static readonly pictureIndexedColors = 234;
11 | public static readonly pictureType = PictureType.ColoredFish;
12 | public static readonly pictureBytes = ByteVector.concatenate(
13 | ByteVector.fromUint(XiphTestResources.pictureType),
14 | ByteVector.fromUint(XiphTestResources.pictureMimeType.length),
15 | ByteVector.fromString(XiphTestResources.pictureMimeType, StringType.UTF8),
16 | ByteVector.fromUint(XiphTestResources.pictureDescription.length),
17 | ByteVector.fromString(XiphTestResources.pictureDescription, StringType.UTF8),
18 | ByteVector.fromUint(XiphTestResources.pictureWidth),
19 | ByteVector.fromUint(XiphTestResources.pictureHeight),
20 | ByteVector.fromUint(XiphTestResources.pictureColorDepth),
21 | ByteVector.fromUint(XiphTestResources.pictureIndexedColors),
22 | ByteVector.fromUint(XiphTestResources.pictureData.length),
23 | XiphTestResources.pictureData
24 | );
25 | public static readonly pictureEncodedBytes = XiphTestResources.pictureBytes.toBase64String();
26 | }
27 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "experimentalDecorators": true,
5 | "inlineSources": true,
6 | "module": "commonjs",
7 | "noImplicitAny": true,
8 | "outDir": "./dist",
9 | "sourceMap": true,
10 | "baseUrl": ".",
11 | "paths": {
12 | "*": ["node_modules/*"]
13 | },
14 | "target": "es6"
15 | },
16 | "include": [
17 | "./src/**/*",
18 | ".eslintrc.js"
19 | ],
20 | "typedocOptions": {
21 | "entryPoints": ["./src/index.ts"],
22 | "out": "docs/",
23 | "excludeInternal": true,
24 | "excludePrivate": true,
25 | "disableSources": true,
26 | "validation": {
27 | "invalidLink": true,
28 | "notDocumented": true
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------