feat(search): populate audio and gps-altitude facets from tika, drop the audio-only gate

This commit is contained in:
Dominik Schmidt
2026-07-30 00:11:01 +02:00
parent 69a6d8afb3
commit c7c0551dbb
5 changed files with 88 additions and 25 deletions

View File

@@ -90,10 +90,7 @@ func (t Tika) Extract(ctx context.Context, ri *provider.ResourceInfo) (Document,
doc.Location = t.getLocation(meta)
doc.Image = t.getImage(meta)
doc.Photo = t.getPhoto(meta)
if contentType, err := getFirstValue(meta, "Content-Type"); err == nil && strings.HasPrefix(contentType, "audio/") {
doc.Audio = t.getAudio(meta)
}
doc.Audio = t.getAudio(meta)
}
if langCode, _ := t.tika.LanguageString(ctx, doc.Content); langCode != "" && t.CleanStopWords {

View File

@@ -30,9 +30,23 @@ func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio {
audio.SetArtist(v)
}
// TODO: audio.Bitrate: not provided by tika
// TODO: audio.Composers: not provided by tika
// TODO: audio.Copyright: not provided by tika for audio files?
if v, err := getFirstValue(meta, "audio:bitrate"); err == nil {
// tika emits bits per second, graph wants kbps
if bps, err := strconv.ParseInt(v, 10, 64); err == nil {
initAudio()
audio.SetBitrate(bps / 1000)
}
}
if v, err := getFirstValue(meta, "xmpDM:composer"); err == nil {
initAudio()
audio.SetComposers(v)
}
if v, err := getFirstValue(meta, "xmpDM:copyright"); err == nil {
initAudio()
audio.SetCopyright(v)
}
if v, err := getFirstValue(meta, "xmpDM:discNumber"); err == nil {
if i, err := strconv.ParseInt(v, 10, 32); err == nil {
@@ -42,7 +56,12 @@ func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio {
}
// TODO: audio.DiscCount: not provided by tika
if v, err := getFirstValue(meta, "audio:disc-count"); err == nil {
if i, err := strconv.ParseInt(v, 10, 32); err == nil {
initAudio()
audio.SetDiscCount(int32(i))
}
}
if v, err := getFirstValue(meta, "xmpDM:duration"); err == nil {
// Tika emits fractional seconds.
@@ -57,8 +76,19 @@ func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio {
audio.SetGenre(v)
}
// TODO: audio.HasDrm: not provided by tika
// TODO: audio.IsVariableBitrate: not provided by tika
if v, err := getFirstValue(meta, "audio:has-drm"); err == nil {
if b, err := strconv.ParseBool(v); err == nil {
initAudio()
audio.SetHasDrm(b)
}
}
if v, err := getFirstValue(meta, "audio:is-variable-bitrate"); err == nil {
if b, err := strconv.ParseBool(v); err == nil {
initAudio()
audio.SetIsVariableBitrate(b)
}
}
if v, err := getFirstValue(meta, "dc:title"); err == nil {
initAudio()
@@ -72,7 +102,12 @@ func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio {
}
}
// TODO: audio.TrackCount: not provided by tika
if v, err := getFirstValue(meta, "audio:track-count"); err == nil {
if i, err := strconv.ParseInt(v, 10, 32); err == nil {
initAudio()
audio.SetTrackCount(int32(i))
}
}
if v, err := getFirstValue(meta, "xmpDM:releaseDate"); err == nil {
if i, err := strconv.ParseInt(v, 10, 32); err == nil {

View File

@@ -9,15 +9,22 @@ import (
var _ = Describe("getAudio", func() {
It("maps the audio metadata to the audio facet", func() {
meta := map[string][]string{
"xmpDM:genre": {"Some Genre"},
"xmpDM:album": {"Some Album"},
"xmpDM:trackNumber": {"7"},
"xmpDM:discNumber": {"4"},
"xmpDM:releaseDate": {"2004"},
"xmpDM:artist": {"Some Artist"},
"xmpDM:albumArtist": {"Some AlbumArtist"},
"dc:title": {"Some Title"},
"xmpDM:duration": {"225.5"},
"xmpDM:genre": {"Some Genre"},
"xmpDM:album": {"Some Album"},
"xmpDM:trackNumber": {"7"},
"xmpDM:discNumber": {"4"},
"xmpDM:releaseDate": {"2004"},
"xmpDM:artist": {"Some Artist"},
"xmpDM:albumArtist": {"Some AlbumArtist"},
"dc:title": {"Some Title"},
"xmpDM:duration": {"225.5"},
"xmpDM:composer": {"Some Composers"},
"xmpDM:copyright": {"Some Copyright"},
"audio:bitrate": {"192000"},
"audio:is-variable-bitrate": {"true"},
"audio:has-drm": {"false"},
"audio:track-count": {"9"},
"audio:disc-count": {"5"},
}
audio := Tika{}.getAudio(meta)
@@ -26,11 +33,18 @@ var _ = Describe("getAudio", func() {
Expect(audio.Album).To(Equal(libregraph.PtrString("Some Album")))
Expect(audio.AlbumArtist).To(Equal(libregraph.PtrString("Some AlbumArtist")))
Expect(audio.Artist).To(Equal(libregraph.PtrString("Some Artist")))
Expect(audio.Bitrate).To(Equal(libregraph.PtrInt64(192)))
Expect(audio.Composers).To(Equal(libregraph.PtrString("Some Composers")))
Expect(audio.Copyright).To(Equal(libregraph.PtrString("Some Copyright")))
Expect(audio.Disc).To(Equal(libregraph.PtrInt32(4)))
Expect(audio.DiscCount).To(Equal(libregraph.PtrInt32(5)))
Expect(audio.Duration).To(Equal(libregraph.PtrInt64(225500)))
Expect(audio.Genre).To(Equal(libregraph.PtrString("Some Genre")))
Expect(audio.HasDrm).To(Equal(libregraph.PtrBool(false)))
Expect(audio.IsVariableBitrate).To(Equal(libregraph.PtrBool(true)))
Expect(audio.Title).To(Equal(libregraph.PtrString("Some Title")))
Expect(audio.Track).To(Equal(libregraph.PtrInt32(7)))
Expect(audio.TrackCount).To(Equal(libregraph.PtrInt32(9)))
Expect(audio.Year).To(Equal(libregraph.PtrInt32(2004)))
})

View File

@@ -6,6 +6,9 @@ import (
libregraph "github.com/opencloud-eu/libre-graph-api-go"
)
// graph geoCoordinates.altitude is in feet, exif GPS altitude (geo:alt) in metres.
const metresToFeet = 3.280839895
func (t Tika) getLocation(meta map[string][]string) *libregraph.GeoCoordinates {
var location *libregraph.GeoCoordinates
initLocation := func() {
@@ -14,10 +17,6 @@ func (t Tika) getLocation(meta map[string][]string) *libregraph.GeoCoordinates {
}
}
// TODO: location.Altitute: transform the following data to … feet above sea level.
// "GPS:GPS Altitude": []string{"227.4 metres"},
// "GPS:GPS Altitude Ref": []string{"Sea level"},
if v, err := getFirstValue(meta, "geo:lat"); err == nil {
if i, err := strconv.ParseFloat(v, 64); err == nil {
initLocation()
@@ -32,5 +31,13 @@ func (t Tika) getLocation(meta map[string][]string) *libregraph.GeoCoordinates {
}
}
// tika emits metres (negative below sea level), graph wants feet
if v, err := getFirstValue(meta, "geo:alt"); err == nil {
if metres, err := strconv.ParseFloat(v, 64); err == nil {
initLocation()
location.SetAltitude(metres * metresToFeet)
}
}
return location
}

View File

@@ -7,14 +7,24 @@ import (
)
var _ = Describe("getLocation", func() {
It("maps latitude and longitude to the location facet", func() {
It("maps lat/long and converts altitude from metres to feet", func() {
metres := 227.4
location := Tika{}.getLocation(map[string][]string{
"geo:lat": {"49.48675890884328"},
"geo:long": {"11.103870357204285"},
"geo:alt": {"227.4"},
})
Expect(location).ToNot(BeNil())
Expect(location.Latitude).To(Equal(libregraph.PtrFloat64(49.48675890884328)))
Expect(location.Longitude).To(Equal(libregraph.PtrFloat64(11.103870357204285)))
Expect(location.Altitude).To(Equal(libregraph.PtrFloat64(metres * metresToFeet)))
})
It("keeps below-sea-level altitude negative", func() {
metres := -227.4
location := Tika{}.getLocation(map[string][]string{"geo:alt": {"-227.4"}})
Expect(location).ToNot(BeNil())
Expect(location.Altitude).To(Equal(libregraph.PtrFloat64(metres * metresToFeet)))
})
It("returns nil when no location metadata is present", func() {