feat: parse flac and ogg audio file
从这个版本开始,播放 flac 和 ogg 格式的音频文件将会从原文件中读取歌曲封面,而不是仅仅通过 Apple Music 搜索获取封面,解决了匹配错误和库中无相关歌曲时无法加载封面的问题。 Beginning with this update, playing audio files in the flac and ogg formats will read the song cover directly from the original file rather than just looking for it on Apple Music. This will fix the issue where the cover won't load when there is a match error and no pertinent song in the library.
This commit is contained in:
parent
6de14140ae
commit
c7fec5ea79
@ -344,6 +344,7 @@ dependencies {
|
||||
implementation "cn.hutool:hutool-crypto:5.7.13"
|
||||
implementation 'cn.hutool:hutool-http:5.7.5'
|
||||
implementation "com.jakewharton:process-phoenix:2.1.2"
|
||||
implementation 'org:jaudiotagger:2.0.3'
|
||||
|
||||
compileOnly 'org.yaml:snakeyaml:1.29'
|
||||
fullImplementation 'org.yaml:snakeyaml:1.29'
|
||||
|
@ -26,6 +26,8 @@ import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import xyz.nextalone.nagram.helper.audio.GenAudioInfo;
|
||||
|
||||
public abstract class AudioInfo {
|
||||
protected String brand; // brand, e.g. "M4A", "ID3", ...
|
||||
protected String version; // version, e.g. "0", "2.3.0", ...
|
||||
@ -145,7 +147,11 @@ public abstract class AudioInfo {
|
||||
if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') {
|
||||
return new M4AInfo(input);
|
||||
} else if (file.getAbsolutePath().endsWith("mp3")) {
|
||||
return new MP3Info(input, file.length());
|
||||
return new MP3Info(input, file.length());
|
||||
} else if (file.getAbsolutePath().endsWith("flac")) {
|
||||
return new GenAudioInfo(file, "FLAC");
|
||||
} else if (file.getAbsolutePath().endsWith("ogg")) {
|
||||
return new GenAudioInfo(file, "OGG");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,84 @@
|
||||
package xyz.nextalone.nagram.helper.audio
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
|
||||
import org.jaudiotagger.audio.AudioFileIO
|
||||
import org.jaudiotagger.tag.FieldKey
|
||||
import org.jaudiotagger.tag.Tag
|
||||
|
||||
import org.telegram.messenger.audioinfo.AudioInfo
|
||||
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.Logger
|
||||
|
||||
import kotlin.math.max
|
||||
|
||||
|
||||
class GenAudioInfo @JvmOverloads constructor(file: File?, format: String? = "FLAC", debugLevel: Level? = Level.FINEST) :
|
||||
AudioInfo() {
|
||||
init {
|
||||
brand = format
|
||||
version = "0"
|
||||
val f = AudioFileIO.read(file)
|
||||
val info = f.tag as Tag
|
||||
val header = f.audioHeader
|
||||
album = info.getFirst(FieldKey.ALBUM)
|
||||
albumArtist = info.getFirst(FieldKey.ALBUM_ARTIST)
|
||||
artist = info.getFirst(FieldKey.ARTIST)
|
||||
comment = info.getFirst(FieldKey.COMMENT)
|
||||
val image = info.artworkList[0]
|
||||
cover = if (image != null) {
|
||||
BitmapFactory.decodeStream(ByteArrayInputStream(image.binaryData))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
if (cover != null) {
|
||||
val scale = max(cover.width, cover.height) / 120.0f
|
||||
smallCover = if (scale > 0) {
|
||||
Bitmap.createScaledBitmap(
|
||||
cover,
|
||||
(cover.width / scale).toInt(),
|
||||
(cover.height / scale).toInt(),
|
||||
true
|
||||
)
|
||||
} else {
|
||||
cover
|
||||
}
|
||||
if (smallCover == null) {
|
||||
smallCover = cover
|
||||
}
|
||||
}
|
||||
compilation = info.getFirst(FieldKey.IS_COMPILATION).toBoolean()
|
||||
composer = info.getFirst(FieldKey.COMPOSER)
|
||||
copyright = ""
|
||||
try {
|
||||
disc = info.getFirst(FieldKey.DISC_NO).toShort()
|
||||
discs = info.getFirst(FieldKey.DISC_TOTAL).toShort()
|
||||
} catch (ignored: NumberFormatException) {}
|
||||
duration = header.trackLength.toLong()
|
||||
genre = info.getFirst(FieldKey.GENRE)
|
||||
grouping = info.getFirst(FieldKey.GROUPING)
|
||||
lyrics = info.getFirst(FieldKey.LYRICS)
|
||||
title = info.getFirst(FieldKey.TITLE)
|
||||
try {
|
||||
track = info.getFirst(FieldKey.TRACK).toShort()
|
||||
tracks = info.getFirst(FieldKey.TRACK_TOTAL).toShort()
|
||||
} catch (ignored: NumberFormatException) {}
|
||||
try {
|
||||
year = info.getFirst(FieldKey.YEAR).toShort()
|
||||
} catch (ignored: NumberFormatException) {}
|
||||
|
||||
if (duration <= 0 || duration >= 3600000L) {
|
||||
if (debugLevel?.let { LOGGER.isLoggable(it) } == true) {
|
||||
LOGGER.log(debugLevel, "Maybe false $format duration.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val LOGGER: Logger = Logger.getLogger(GenAudioInfo::class.java.name)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user