mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-04-06 17:21:58 -04:00
Fix ec3 playback, add channels count in media (#1420)
This commit is contained in:
commit
2d09b2748b
@ -311,6 +311,7 @@
|
||||
"video": "Video",
|
||||
"audio": "Audio",
|
||||
"subtitles": "Subtitles",
|
||||
"channels": "{{channels}} Channels",
|
||||
"forced": "Forced",
|
||||
"hearing-impaired": "CC",
|
||||
"default": "Default",
|
||||
|
||||
@ -35,6 +35,7 @@ export const AudioTrack = z.object({
|
||||
language: z.string().nullable(),
|
||||
codec: z.string(),
|
||||
mimeCodec: z.string().nullable(),
|
||||
channels: z.int(),
|
||||
bitrate: z.number(),
|
||||
isDefault: z.boolean(),
|
||||
});
|
||||
|
||||
@ -94,6 +94,7 @@ export const Info = () => {
|
||||
? t("mediainfo.default")
|
||||
: undefined,
|
||||
x.codec,
|
||||
t("mediainfo.channels", { channels: x.channels }),
|
||||
]
|
||||
.filter((x) => x)
|
||||
.join(" - ")}
|
||||
|
||||
5
transcoder/migrations/000003_add_audio_channels.down.sql
Normal file
5
transcoder/migrations/000003_add_audio_channels.down.sql
Normal file
@ -0,0 +1,5 @@
|
||||
begin;
|
||||
|
||||
alter table gocoder.audios drop column channels;
|
||||
|
||||
commit;
|
||||
6
transcoder/migrations/000003_add_audio_channels.up.sql
Normal file
6
transcoder/migrations/000003_add_audio_channels.up.sql
Normal file
@ -0,0 +1,6 @@
|
||||
begin;
|
||||
|
||||
delete from gocoder.audios;
|
||||
alter table gocoder.audios add column channels int not null default 2;
|
||||
|
||||
commit;
|
||||
@ -100,11 +100,11 @@ func GetMimeCodec(stream *ffprobe.Stream) *string {
|
||||
return &ret
|
||||
|
||||
case "ac3":
|
||||
ret := "mp4a.a5"
|
||||
ret := "ac-3"
|
||||
return &ret
|
||||
|
||||
case "eac3":
|
||||
ret := "mp4a.a6"
|
||||
ret := "ec-3"
|
||||
return &ret
|
||||
|
||||
case "flac":
|
||||
|
||||
@ -77,52 +77,12 @@ func (fs *FileStream) Destroy() {
|
||||
func (fs *FileStream) GetMaster(client string) string {
|
||||
master := "#EXTM3U\n"
|
||||
|
||||
for _, audio := range fs.Info.Audios {
|
||||
for _, quality := range AudioQualities {
|
||||
master += "#EXT-X-MEDIA:TYPE=AUDIO,"
|
||||
master += fmt.Sprintf("GROUP-ID=\"audio-%s\",", quality)
|
||||
if audio.Language != nil {
|
||||
master += fmt.Sprintf("LANGUAGE=\"%s\",", *audio.Language)
|
||||
}
|
||||
if audio.Title != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Title)
|
||||
} else if audio.Language != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Language)
|
||||
} else {
|
||||
master += fmt.Sprintf("NAME=\"Audio %d\",", audio.Index)
|
||||
}
|
||||
if audio.IsDefault {
|
||||
master += "DEFAULT=YES,"
|
||||
}
|
||||
master += "CHANNELS=\"2\","
|
||||
master += fmt.Sprintf("URI=\"audio/%d/%s/index.m3u8?clientId=%s\"\n", audio.Index, quality, client)
|
||||
}
|
||||
master += "#EXT-X-MEDIA:TYPE=AUDIO,"
|
||||
master += fmt.Sprintf("GROUP-ID=\"audio-%s\",", AOriginal)
|
||||
if audio.Language != nil {
|
||||
master += fmt.Sprintf("LANGUAGE=\"%s\",", *audio.Language)
|
||||
}
|
||||
if audio.Title != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Title)
|
||||
} else if audio.Language != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Language)
|
||||
} else {
|
||||
master += fmt.Sprintf("NAME=\"Audio %d\",", audio.Index)
|
||||
}
|
||||
if audio.IsDefault {
|
||||
master += "DEFAULT=YES,"
|
||||
}
|
||||
master += "CHANNELS=\"2\"," // TODO
|
||||
master += fmt.Sprintf("URI=\"audio/%d/%s/index.m3u8?clientId=%s\"\n", audio.Index, AOriginal, client)
|
||||
}
|
||||
|
||||
// codec is the prefix + the level, the level is not part of the codec we want to compare for the same_codec check bellow
|
||||
transcode_prefix := "avc1.6400"
|
||||
transcode_codec := transcode_prefix + "28"
|
||||
transcode_audio_codec := "mp4a.40.2"
|
||||
|
||||
var def_video *Video
|
||||
var def_audio *Audio
|
||||
for _, video := range fs.Info.Videos {
|
||||
if video.IsDefault {
|
||||
def_video = &video
|
||||
@ -132,10 +92,53 @@ func (fs *FileStream) GetMaster(client string) string {
|
||||
if def_video == nil && len(fs.Info.Videos) > 0 {
|
||||
def_video = &fs.Info.Videos[0]
|
||||
}
|
||||
if len(fs.Info.Audios) > 0 {
|
||||
|
||||
var def_audio *Audio
|
||||
for _, audio := range fs.Info.Audios {
|
||||
if audio.IsDefault {
|
||||
def_audio = &audio
|
||||
break
|
||||
}
|
||||
}
|
||||
if def_audio == nil && len(fs.Info.Audios) > 0 {
|
||||
def_audio = &fs.Info.Audios[0]
|
||||
}
|
||||
|
||||
if def_audio != nil {
|
||||
aqualities := utils.Filter(AudioQualities, func(quality AudioQuality) bool {
|
||||
return quality.Bitrate() < def_audio.Bitrate
|
||||
})
|
||||
aqualities = append(aqualities, AOriginal)
|
||||
|
||||
for _, audio := range fs.Info.Audios {
|
||||
for _, quality := range slices.Backward(aqualities) {
|
||||
master += "#EXT-X-MEDIA:TYPE=AUDIO,"
|
||||
master += fmt.Sprintf("GROUP-ID=\"a-%s\",", quality)
|
||||
if audio.Language != nil {
|
||||
master += fmt.Sprintf("LANGUAGE=\"%s\",", *audio.Language)
|
||||
}
|
||||
if audio.Title != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Title)
|
||||
} else if audio.Language != nil {
|
||||
master += fmt.Sprintf("NAME=\"%s\",", *audio.Language)
|
||||
} else {
|
||||
master += fmt.Sprintf("NAME=\"Audio %d\",", audio.Index)
|
||||
}
|
||||
if audio == *def_audio {
|
||||
master += "DEFAULT=YES,"
|
||||
}
|
||||
if quality == AOriginal {
|
||||
master += fmt.Sprintf("CHANNELS=\"%d\",", audio.Channels)
|
||||
} else {
|
||||
master += "CHANNELS=\"2\","
|
||||
}
|
||||
master += fmt.Sprintf("URI=\"audio/%d/%s/index.m3u8?clientId=%s\"\n", audio.Index, quality, client)
|
||||
}
|
||||
master += "\n"
|
||||
}
|
||||
master += "\n"
|
||||
}
|
||||
|
||||
if def_video != nil {
|
||||
qualities := utils.Filter(VideoQualities, func(quality VideoQuality) bool {
|
||||
return quality.Height() < def_video.Height
|
||||
@ -148,8 +151,8 @@ func (fs *FileStream) GetMaster(client string) string {
|
||||
}
|
||||
qualities = append(qualities, Original)
|
||||
|
||||
for _, quality := range qualities {
|
||||
for _, video := range fs.Info.Videos {
|
||||
for _, video := range fs.Info.Videos {
|
||||
for _, quality := range slices.Backward(qualities) {
|
||||
master += "#EXT-X-MEDIA:TYPE=VIDEO,"
|
||||
master += fmt.Sprintf("GROUP-ID=\"%s\",", quality)
|
||||
if video.Language != nil {
|
||||
@ -168,6 +171,7 @@ func (fs *FileStream) GetMaster(client string) string {
|
||||
master += fmt.Sprintf("URI=\"%d/%s/index.m3u8?clientId=%s\"\n", video.Index, quality, client)
|
||||
}
|
||||
}
|
||||
master += "\n"
|
||||
}
|
||||
master += "\n"
|
||||
|
||||
@ -178,23 +182,35 @@ func (fs *FileStream) GetMaster(client string) string {
|
||||
if def_audio != nil && (def_audio.MimeCodec == nil || *def_audio.MimeCodec != transcode_audio_codec) {
|
||||
audios = append(audios, matchAudioQuality(def_video.Quality()))
|
||||
}
|
||||
for _, audio_quality := range audios {
|
||||
for _, aquality := range audios {
|
||||
// original & noresize streams
|
||||
bitrate := float64(def_video.Bitrate)
|
||||
master += "#EXT-X-STREAM-INF:"
|
||||
master += fmt.Sprintf("AVERAGE-BANDWIDTH=%d,", int(math.Min(bitrate*0.8, float64(def_video.Quality().AverageBitrate()))))
|
||||
master += fmt.Sprintf("BANDWIDTH=%d,", int(math.Min(bitrate, float64(def_video.Quality().MaxBitrate()))))
|
||||
master += fmt.Sprintf("RESOLUTION=%dx%d,", def_video.Width, def_video.Height)
|
||||
var audio_codec = transcode_audio_codec
|
||||
if def_audio != nil && audio_quality == AOriginal {
|
||||
audio_codec = *def_audio.MimeCodec
|
||||
|
||||
codecs := make([]string, 0)
|
||||
if quality == Original {
|
||||
if def_video.MimeCodec != nil {
|
||||
codecs = append(codecs, *def_video.MimeCodec)
|
||||
}
|
||||
} else {
|
||||
codecs = append(codecs, transcode_codec)
|
||||
}
|
||||
if quality != Original {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transcode_codec, audio_codec}, ","))
|
||||
} else if def_video.MimeCodec != nil {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{*def_video.MimeCodec, audio_codec}, ","))
|
||||
if aquality == AOriginal {
|
||||
if def_audio != nil && def_audio.MimeCodec != nil {
|
||||
codecs = append(codecs, *def_audio.MimeCodec)
|
||||
}
|
||||
} else {
|
||||
codecs = append(codecs, transcode_audio_codec)
|
||||
}
|
||||
if len(codecs) > 0 {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join(codecs, ","))
|
||||
}
|
||||
if def_audio != nil {
|
||||
master += fmt.Sprintf("AUDIO=\"a-%s\",", string(aquality))
|
||||
}
|
||||
master += fmt.Sprintf("AUDIO=\"audio-%s\",", string(audio_quality))
|
||||
master += "CLOSED-CAPTIONS=NONE\n"
|
||||
master += fmt.Sprintf("%d/%s/index.m3u8?clientId=%s\n", def_video.Index, quality, client)
|
||||
}
|
||||
@ -206,7 +222,9 @@ func (fs *FileStream) GetMaster(client string) string {
|
||||
master += fmt.Sprintf("BANDWIDTH=%d,", quality.MaxBitrate())
|
||||
master += fmt.Sprintf("RESOLUTION=%dx%d,", int(aspectRatio*float32(quality.Height())+0.5), quality.Height())
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transcode_codec, transcode_audio_codec}, ","))
|
||||
master += fmt.Sprintf("AUDIO=\"audio-%s\",", string(matchAudioQuality(quality)))
|
||||
if def_audio != nil {
|
||||
master += fmt.Sprintf("AUDIO=\"a-%s\",", string(matchAudioQuality(quality)))
|
||||
}
|
||||
master += "CLOSED-CAPTIONS=NONE\n"
|
||||
master += fmt.Sprintf("%d/%s/index.m3u8?clientId=%s\n", def_video.Index, quality, client)
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ import (
|
||||
"gopkg.in/vansante/go-ffprobe.v2"
|
||||
)
|
||||
|
||||
const InfoVersion = 3
|
||||
const InfoVersion = 4
|
||||
|
||||
type Versions struct {
|
||||
Info int32 `json:"info" db:"ver_info"`
|
||||
@ -98,6 +98,8 @@ type Audio struct {
|
||||
Codec string `json:"codec" db:"codec"`
|
||||
/// The codec of this stream (defined as the RFC 6381).
|
||||
MimeCodec *string `json:"mimeCodec" db:"mime_codec"`
|
||||
/// The number of channels that stream has.
|
||||
Channels int `json:"channels" db:"channels"`
|
||||
/// The average bitrate of the audio in bytes/s
|
||||
Bitrate uint32 `json:"bitrate" db:"bitrate"`
|
||||
/// Is this stream the default one of it's type?
|
||||
@ -280,6 +282,7 @@ func RetriveMediaInfo(path string, sha string) (*MediaInfo, error) {
|
||||
Language: NullIfUnd(lang.String()),
|
||||
Codec: stream.CodecName,
|
||||
MimeCodec: GetMimeCodec(stream),
|
||||
Channels: stream.Channels,
|
||||
Bitrate: ParseUint(cmp.Or(stream.BitRate, mi.Format.BitRate)),
|
||||
IsDefault: stream.Disposition.Default != 0,
|
||||
}
|
||||
|
||||
@ -318,8 +318,8 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
|
||||
tx.Exec(
|
||||
ctx,
|
||||
`
|
||||
insert into gocoder.audios(sha, idx, title, language, codec, mime_codec, is_default, bitrate)
|
||||
values ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
insert into gocoder.audios(sha, idx, title, language, codec, mime_codec, channels, is_default, bitrate)
|
||||
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
on conflict (sha, idx) do update set
|
||||
sha = excluded.sha,
|
||||
idx = excluded.idx,
|
||||
@ -327,10 +327,11 @@ func (s *MetadataService) storeFreshMetadata(ctx context.Context, path string, s
|
||||
language = excluded.language,
|
||||
codec = excluded.codec,
|
||||
mime_codec = excluded.mime_codec,
|
||||
channels = excluded.channels,
|
||||
is_default = excluded.is_default,
|
||||
bitrate = excluded.bitrate
|
||||
`,
|
||||
ret.Sha, a.Index, a.Title, a.Language, a.Codec, a.MimeCodec, a.IsDefault, a.Bitrate,
|
||||
ret.Sha, a.Index, a.Title, a.Language, a.Codec, a.MimeCodec, a.Channels, a.IsDefault, a.Bitrate,
|
||||
)
|
||||
}
|
||||
for _, s := range ret.Subtitles {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user