improve file scanning
MREADME.md
@@ -60,7 +60,7 @@ You can configure the backend with the following environment variables:
## Known issues
- Range requests are not correctly handled in Bun right now, and e.g. doesn't send the total byte length correctly. I worked around this by sending a chunked transfer-encoded response, and setting the range and content-length header manually, which seems to work with the browsers I tested, but still might cause issues in some cases
- Some of the transcoded formats behave weirdly in some browsers, e.g. safari seems to dislike ogg containers, and chrome has seeking issues with some webm transcoded files. If you have any code suggestions to improve the handling, feel free to open a PR at https://gitlab.com/Konata390/pico-pixel-player
- Some files (especially mp3) fail to either be listed or to be played. I encountered some mp3 files that could be played fine, but had some weird metadata issues that caused the file-type/music-metadata libraries to not be able to scan them, which blocks them from being played in the browsers. The solution is to run `ffmpeg -i INPUTFILE -c copy OUTPUTFILE` on them, afterwards they are scanned just fine
- Some files (especially mp3) have weird metadata issues (e.g. a padding gap between the ID3 tag and the first frame sync) that stop the `file-type` library from identifying them. The server now falls back to `mediainfo` for MIME detection in that case, so these files list and stream normally without any intervention. If a file still fails to be listed or played, running `ffmpeg -i INPUTFILE -c copy OUTPUTFILE` on it to rewrite the container usually fixes it
## Attributions
Mserver/src/utils.ts
@@ -215,6 +215,19 @@ export async function getPathInfo(filePath: string): Promise<PathInfo | ServerEr
//fileTypeFromBlob uses the statically bundled strtok3/core instead
const type = await fileTypeFromBlob(Bun.file(filePath));
mimeType = type?.mime;
if (!mimeType) {
//fileTypeFromBlob gives up on some valid media (e.g. MP3s padded before the first frame sync).
//confirm the file is genuinely decodable with mediainfo (probeFile caches the result, so the probe
//listFiles runs next for this same file is a cache hit, not a second mediainfo spawn), then take the
//MIME type from the extension via Bun's mime-db, accepting only audio/video types.
try {
await probeFile(filePath);
const byExtension = Bun.file(filePath).type.split(";", 1)[0];
if (matchesType(byExtension, mediaTypes)) mimeType = byExtension;
} catch {
//not decodable media (e.g. a genuinely unrecognised file); fall through to the error below
}
}
if (mimeType) {
fileTypeCache.set(filePath, mimeType);
} else {