init: dec-music 项目初始化
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package tm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"jsuse.com/dev/dec-music/decrypt"
|
||||
"jsuse.com/dev/dec-music/internal/sniff"
|
||||
)
|
||||
|
||||
var replaceHeader = []byte{0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}
|
||||
var magicHeader = []byte{0x51, 0x51, 0x4D, 0x55} //0x15, 0x1D, 0x1A, 0x21
|
||||
|
||||
type decoder struct {
|
||||
raw io.ReadSeeker // raw is the original file reader
|
||||
|
||||
offset int
|
||||
audio io.Reader // audio is the decrypted audio data
|
||||
}
|
||||
|
||||
func (d *decoder) Validate() error {
|
||||
header := make([]byte, 8)
|
||||
if _, err := io.ReadFull(d.raw, header); err != nil {
|
||||
return fmt.Errorf("tm read header: %w", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(magicHeader, header[:len(magicHeader)]) { // replace m4a header
|
||||
d.audio = io.MultiReader(bytes.NewReader(replaceHeader), d.raw)
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, ok := sniff.AudioExtension(header); ok { // not encrypted
|
||||
d.audio = io.MultiReader(bytes.NewReader(header), d.raw)
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("tm: valid magic header")
|
||||
}
|
||||
|
||||
func (d *decoder) Read(buf []byte) (int, error) {
|
||||
return d.audio.Read(buf)
|
||||
}
|
||||
|
||||
func newTmDecoder(p *decrypt.DecoderParams) decrypt.Decoder {
|
||||
return &decoder{raw: p.Reader}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// QQ Music IOS M4a (replace header)
|
||||
decrypt.RegisterDecoder("tm2", false, newTmDecoder)
|
||||
decrypt.RegisterDecoder("tm6", false, newTmDecoder)
|
||||
decrypt.RegisterDecoder("tm0", false, newTmDecoder)
|
||||
decrypt.RegisterDecoder("tm3", false, newTmDecoder)
|
||||
}
|
||||
Reference in New Issue
Block a user