Skip to contents

Reads the embedded metadata of an audio file, whatever format that metadata is in and whatever container the file is: GUANO, Wildlife Acoustics wamd, Broadcast Wave bext, iXML and the INFO list from a wave file, the AudioMoth comment, ID3 from an MP3 file or from a wave file that holds a tag in a chunk, and Vorbis comments from a FLAC or Ogg file. A file holding none of them gives an empty result rather than an error. A wave file over 4 GiB, written in the RF64 or BW64 form, is read as any other, and named by that form.

Usage

readMetadata(x, filename = TRUE)

Arguments

x

Path to an audio file, a Wave object with metadata attached, or a raw vector holding a file

filename

Whether to read the name of the file as well as its contents. TRUE works the format out from the name, FALSE reads only what is inside the file, and the name of one of parseFilename()'s formats reads the name as that, which settles a name the package could not have settled on its own.

Value

An audioMetadata object. file and container are always there, so its length says nothing about whether the file carried any metadata: ask length(x$sources) for that, or length(x$fields) for whether anything was read that this package has a normalised name for.

Details

A recording commonly carries more than one of these formats, written by the device that made it and by whatever software has handled it since, and the same fact under a different name in each. The result therefore holds both what each format said and one normalised record built from all of them:

file

The path the metadata was read from, or NA

container

The kind of file it was read from, read from the bytes of the file rather than from its name, or NA where it is not one this package recognises

fields

The normalised record (see below)

sources

The formats that were found, each as the object its own reader gives, named guano, wamd, audiomoth, olym, bext, ixml, xenoCanto, wavInfo, xmp, disp, id3, vorbisComment and filename. A format the file does not carry is left out.

unparsed

The identifiers of any chunks the file holds that carry metadata this package cannot read, such as the proprietary block an editor leaves behind. Knowing they are there is worth more than passing over them in silence.

The normalised record

fields holds whichever of datetime, make, model, serial, firmware, software, prefix, microphone, title, species, recordist, comment, note, licence, url, location, elevation, collection, project and take the file said anything about. location is a latitude and a longitude in degrees, and datetime is a POSIXct wherever the file gave enough to make one.

Where two formats say the same thing, the one that is believed is the first of GUANO, wamd, the AudioMoth comment, bext, iXML, the xeno-canto record, the INFO list, ID3, Vorbis comments and the filename: a format written for bioacoustics is trusted over one written for broadcast, a recorder's own writing over a collection's transcription of what it was told, and anything written inside the file over anything read from its name. Nothing is thrown away by this, as sources still holds what every format said.

That order says which format to believe, not which copy a writer got right. A file can carry the same string in two places and have been written correctly in one and badly in the other, and the record then takes whichever the order puts first, mistake and all. One file of 972 in a cached copy of the iNaturalist corpus holds an original filename in both its INFO list and its ID3 tag, where the recorder wrote UTF-8 into the tag and the same text double-encoded into the list; the list outranks the tag, so title comes back mangled although the file holds a good copy. Both readings are in sources and neither is altered, so where a field matters and the file carries it twice, it is worth comparing sources rather than taking fields on its own.

A field that holds only a year gives no datetime, as it has no month or day to make one with; the year can still be read from the source that gave it. Species are taken only from a format that names a species as such, and never guessed at from a title.

A time in an ID3 tag that names no zone is read as UTC, which version 2.4 of the format says every time in it is, rather than as a wall clock in the zone of the session, as one in an INFO list, an XMP packet or a Vorbis comment is read. It comes back in UTC, so it prints as the tag wrote it whatever the zone of the session, and it may stop at the hour, as the format allows.

The xeno-canto record

A recording from the xeno-canto collection carries a comment the collection wrote, beginning with its catalogue number, as XC428067 (c) A Recordist // Locality (1.4, 103.7), Singapore // 10m // 15:00h, 2019-02-03 // call // remarks. It is read into a xenoCanto source holding the number, recordist, locality, latitude, longitude, country, elevation, time, date, kind of vocalisation, remarks, whether the bird was seen and whether playback was used, and the other species audible, and it gives the record a datetime, a location and an elevation that are otherwise nowhere in the file.

The catalogue number at the head of the comment is what marks it as one of theirs, so a comment somebody else wrote is left alone. The number is the recording's rather than the file's: a recording downloaded from the collection and uploaded elsewhere keeps its comment and gains a new name, and is read the same wherever it has got to.

What the collection was not told it writes as a placeholder rather than leaving out, so a time of ?h, an elevation of ?m or a date with a zero month or day is an absence and is read as one. A time nothing can read costs only the datetime; the date is still in the source. The species in also: are the others audible in the recording rather than the one it is of, so they are not reported as its species.

Reading from a name

filename reads the filename conventions that parseFilename() knows, and is the one source nothing outranks: where the file itself said nothing, what its name says is the whole answer. Pass filename=FALSE to read only what is inside the file.

Because nothing outranks it, a reading the name left in doubt gives no datetime. A name of nothing but digits is read as a date or as a count of seconds, and a collection that numbers its records gives names of exactly that shape, so a date taken from one would often be a confident wrong answer with nothing beside it to correct it.

Where you know what your own files are named by, say so: filename takes the name of a filename format as well as TRUE or FALSE, as in filename = "YYYYMMDD". Naming it settles what those digits mean, so the date is read and used rather than passed over as a guess. The formats are those parseFilename() lists.

A TSA name gives a species and a collection. That corpus commonly holds no embedded metadata at all, so for those recordings its name is the only thing there is to read.

See also

The readers for one format at a time: guano(), wamd(), bext(), ixml(), wavInfo(), id3() and vorbisComment(). The AudioMoth comment has no reader of its own any more: audiomothWave() is deprecated in favour of the audiomoth source this returns. audioMetadata<- attaches a reading to a Wave object.

Examples

f <- system.file("extdata/AUDIOMOTH_GUANO.WAV", package="sonicscrewdriver")
m <- readMetadata(f)
m$fields$model
#> [1] "AudioMoth"
m$sources$guano
#> GUANO|Version          1.0
#> Make                   Open Acoustic Devices
#> Model                  AudioMoth
#> Serial                 247AB4055C7B17DB
#> Firmware Version       AudioMoth-Firmware-Basic (1.11.0)
#> Timestamp              2026-05-14T20:06:00Z
#> Loc Position           51.4964 -0.1224
#> OAD|Loc Source         Configuration app
#> Original Filename      20260514_210600.WAV
#> OAD|Recording Settings 8000 GAIN 2 AMP 1000 1
#> OAD|Battery Voltage    4.1
#> Temperature Int        12.3