Skip to content

Find the tonie by audio id and hash for the live title and track names - #569

Open
zimmermq wants to merge 1 commit into
toniebox-reverse-engineering:developfrom
zimmermq:fix-audioid-hash-lookup
Open

zimmermq wants to merge 1 commit into
toniebox-reverse-engineering:developfrom
zimmermq:fix-audioid-hash-lookup

Conversation

@zimmermq

Copy link
Copy Markdown

Refs #430, #194

What

When the box plays a tonie, the title and picture sent over SSE and MQTT can belong to another tonie. The audio id is the time the audio was encoded, and tonies encoded in the same second share it; only the hash tells them apart. The title lookup used the audio id alone and took the first match. In the current tonies.json that gives about 30 tonies another tonie's title, for example Glumanda shows as Pikachu (toniebox-reverse-engineering/tonies-json#354), Hercules and Ratatouille as The Incredibles, and Joke of the Day as Today with tonies Podcast on 321 of its days. The track names of a track export had the same problem.

In #430 you named the MQTT selection as the one place that does not go through the tag (RUID, content json, model) and said it could be fixed. This goes through the tag to its TAF and identifies the content by audio id and hash, as you described for content:

  • Live title: the box reports only the audio id. If the TAF of the tag on the box has that audio id, its hash picks the tonie. When the hash is unknown, it falls back to the audio id alone and then to the tag's model, as before.
  • Track export: uses the hash from the TAF header, with the same fallback to the audio id, so a re-encoded copy still gets track names.

Side effects in the audio id handler, which now reads the tag's content on every audio id:

  • It reads only when the box reports a valid tag. A late log entry with no tag (uid 0) created content for tag 0, and an invalid tag got content created for it; both no longer happen, so an invalid tag also no longer falls back to its model.
  • Audio id 1, the empty content of creative tonies, is still told apart only by the tag's model, as many creative tonies share its hash.
  • ContentAudioId is sent together with ContentTitle and ContentPicture, after the lookup. With "Full TAF validation" on, the read hashes the whole TAF and delays these events.
  • A tonies.custom.json entry with the same audio id but another hash no longer wins over the tonies.json entry with the TAF's hash.

ContentTitle and ContentPicture stay the content: in #194 you wrote that two separate blocks are needed, one for the selected model and one for the actual content, and the web UI shows them that way. Taking the tag's model first would show the figurine instead of what plays for a tag with other content (a library TAF, a creative tonie with store content). A separate figurine block from the tag's model, which would also tell a coin from a figurine with the same audio, could be a small follow-up if you want it.

Not fixed here: without the TAF in teddyCloud, the title still comes from the audio id alone.

Test

  • tests/py/test_audio_id_collision.py (make test_py TESTS=audio_id_collision), with the simulated box:
    • two entries with the same audio id and different hashes, in both orders: the title of the tag's own TAF.
    • audio id 1: the tag's model, even when another entry has the TAF's hash; with no tag, Unknown.
    • an audio id with no tag, and with an invalid tag: no content is created.
  • tests/py/test_track_export.py: the same collision, in both orders, for the track names in the export zip.

Verified (built on develop 907acea, Ubuntu 26.04, arm64, sanitizers on)

  • Without this change: the collision tests fail in the order with the other tonie first, the no-tag test finds content created for tag 0, and the invalid-tag test finds a content json created for that tag.
  • With this change: all pass. make test passes.

@henryk86

henryk86 commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

This circumstance also causes problems with downloading and caching the content to the library.

By default the taf files are stored with audioid.taf. In case of those tonies (Pokémon) the first Tonie placed of such couples wins and the second one gets not copy to the library.

This should be maybe changed to a more intelligent migration. Instead of cancelling the migration if the same named file is in the folder already, it should compare the hash also and then migrate it with a suffix.

@zimmermq

zimmermq commented Nov 1, 2026

Copy link
Copy Markdown
Author

Thanks, good point. That is a separate problem from this PR (which only fixes the title lookup), so I opened #574 for it with a proposal: when <audio id>.taf is already taken by a file with a different hash, store the second one as <audio id>-<first 8 hex digits of the SHA1>.taf instead of leaving it in the content folder. I will send a PR for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants