A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: default to music-metadata because mediainfo.js has encoding issues

+50 -14
+28
package-lock.json
··· 12 12 "@oddjs/odd": "^0.37.2", 13 13 "@tokenizer/http": "^0.6.2", 14 14 "elm-taskport": "^2.0.1", 15 + "encoding-japanese": "^2.0.0", 15 16 "fast-text-encoding": "^1.0.6", 16 17 "file-saver": "^2.0.2", 18 + "jschardet": "^3.0.0", 17 19 "jszip": "^3.7.1", 18 20 "load-script2": "^2.0.5", 19 21 "localforage": "^1.10.0", ··· 3195 3197 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 3196 3198 "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 3197 3199 }, 3200 + "node_modules/encoding-japanese": { 3201 + "version": "2.0.0", 3202 + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", 3203 + "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==", 3204 + "engines": { 3205 + "node": ">=8.10.0" 3206 + } 3207 + }, 3198 3208 "node_modules/end-of-stream": { 3199 3209 "version": "1.4.4", 3200 3210 "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", ··· 4942 4952 "js-yaml": "bin/js-yaml.js" 4943 4953 } 4944 4954 }, 4955 + "node_modules/jschardet": { 4956 + "version": "3.0.0", 4957 + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz", 4958 + "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==", 4959 + "engines": { 4960 + "node": ">=0.1.90" 4961 + } 4962 + }, 4945 4963 "node_modules/json-buffer": { 4946 4964 "version": "3.0.1", 4947 4965 "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", ··· 9747 9765 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 9748 9766 "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 9749 9767 }, 9768 + "encoding-japanese": { 9769 + "version": "2.0.0", 9770 + "resolved": "https://registry.npmjs.org/encoding-japanese/-/encoding-japanese-2.0.0.tgz", 9771 + "integrity": "sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==" 9772 + }, 9750 9773 "end-of-stream": { 9751 9774 "version": "1.4.4", 9752 9775 "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", ··· 10957 10980 "requires": { 10958 10981 "argparse": "^2.0.1" 10959 10982 } 10983 + }, 10984 + "jschardet": { 10985 + "version": "3.0.0", 10986 + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-3.0.0.tgz", 10987 + "integrity": "sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==" 10960 10988 }, 10961 10989 "json-buffer": { 10962 10990 "version": "3.0.1",
+2
package.json
··· 34 34 "@oddjs/odd": "^0.37.2", 35 35 "@tokenizer/http": "^0.6.2", 36 36 "elm-taskport": "^2.0.1", 37 + "encoding-japanese": "^2.0.0", 37 38 "fast-text-encoding": "^1.0.6", 38 39 "file-saver": "^2.0.2", 40 + "jschardet": "^3.0.0", 39 41 "jszip": "^3.7.1", 40 42 "load-script2": "^2.0.5", 41 43 "localforage": "^1.10.0",
+20 -14
src/Javascript/processing.ts
··· 7 7 import type { IAudioMetadata } from "music-metadata"; 8 8 import type { MediaInfo, MediaInfoType } from "mediainfo.js"; 9 9 10 - import MediaInfoFactory from "mediainfo.js"; 11 10 import * as Uint8arrays from "uint8arrays"; 12 - 13 11 import { transformUrl } from "./urls"; 14 12 15 13 // Contexts ··· 61 59 headUrl: string, 62 60 getUrl: string, 63 61 filename: string, 64 - mediainfo: MediaInfo<"object">, 62 + { covers }: { covers: boolean }, 65 63 ) { 66 - const miResult = await mediainfo 67 - .analyzeData(getSize(headUrl), readChunk(getUrl)) 68 - .catch((_) => null); 69 - const miTags = miResult && pickTagsFromMediaInfo(filename, miResult); 70 - if (miTags) return miTags; 71 - 72 64 const musicMetadata = await import("music-metadata-browser").then((a) => a.default); 73 65 const httpTokenizer = await import("@tokenizer/http").then((a) => a.default); 74 66 ··· 83 75 tokenizer.rangeRequestClient.resolvedUrl = undefined; 84 76 } 85 77 86 - const mmResult = await musicMetadata.parseFromTokenizer(tokenizer); 78 + const mmResult = await musicMetadata.parseFromTokenizer(tokenizer, { skipCovers: !covers }); 87 79 const mmTags = pickTagsFromMusicMetadata(filename, mmResult); 88 80 if (mmTags) return mmTags; 89 81 82 + const miResult = (await mediaInfoClient()) 83 + .analyzeData(getSize(headUrl), readChunk(getUrl)) 84 + .catch((_) => null); 85 + const miTags = miResult && pickTagsFromMediaInfo(filename, miResult); 86 + if (miTags) return miTags; 87 + 90 88 return fallbackTags(filename); 91 89 } 92 90 ··· 153 151 const tags = result?.media?.track?.filter((t) => t["@type"] === "General")[0]; 154 152 if (!tags) return null; 155 153 156 - let artist = tags.Performer?.length ? tags.Performer : null; 157 - const title = tags.Title?.length ? tags.Title : null; 154 + let artist = typeof tags.Performer == "string" ? tags.Performer : null; 155 + const album = typeof tags.Album == "string" ? tags.Album : null; 156 + 157 + const title = typeof tags.Track == "string" 158 + ? tags.Track 159 + : typeof tags.Title == "string" 160 + ? tags.Title 161 + : null; 158 162 159 163 if (!artist && !title) return null; 164 + if (artist?.includes("�") || album?.includes("�") || title?.includes("�")) return null 160 165 161 166 if (artist && artist.includes(" / ")) { 162 167 artist = artist ··· 170 175 return { 171 176 disc: tags.Part_Position || 1, 172 177 nr: tags.Track_Position || 1, 173 - album: tags.Album && tags.Album.length ? tags.Album : null, 178 + album: album, 174 179 artist: artist, 175 180 title: title || filename.replace(/\.\w+$/, ""), 176 181 genre: tags.Genre || null, ··· 215 220 // -- 216 221 217 222 async function mediaInfoClient() { 223 + const MediaInfoFactory = await import("mediainfo.js").then(a => a.default) 224 + 218 225 return await MediaInfoFactory({ 219 226 coverData: false, 220 - full: true, 221 227 locateFile: () => { 222 228 return "../../wasm/media-info.wasm"; 223 229 },