mirror of
https://github.com/yattee/yattee.git
synced 2026-08-06 07:11:28 +00:00
Label local-file video quality from mpv track info instead of Unknown
Streams built for local folder files carry no resolution/codec/fps metadata (unknowable before demux), so the quality selector labeled them "Unknown". Use the video track mpv reports (demux-w/h/fps, codec) to fill those fields into a display-only copy of the stream — the Video row and summary now show e.g. "720p · 30fps" with a codec badge. Selection and tap handling keep using the original stream.
This commit is contained in:
@@ -866,6 +866,7 @@ extension ExpandedPlayerSheet {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onEmbeddedAudioTrackSelected: { trackID in
|
||||
playerService.selectEmbeddedAudioTrack(trackID)
|
||||
},
|
||||
@@ -1146,6 +1147,7 @@ extension ExpandedPlayerSheet {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onEmbeddedAudioTrackSelected: { trackID in
|
||||
playerService.selectEmbeddedAudioTrack(trackID)
|
||||
},
|
||||
@@ -1533,6 +1535,7 @@ extension ExpandedPlayerSheet {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onEmbeddedAudioTrackSelected: { trackID in
|
||||
playerService.selectEmbeddedAudioTrack(trackID)
|
||||
},
|
||||
|
||||
@@ -701,6 +701,7 @@ private struct PlayerSheetsModifier: ViewModifier {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onStreamSelected: { stream, audioStream in
|
||||
onStreamSelected(stream, audioStream)
|
||||
},
|
||||
|
||||
@@ -266,6 +266,7 @@ struct MPVVideoView: View {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onEmbeddedAudioTrackSelected: { trackID in
|
||||
playerService.selectEmbeddedAudioTrack(trackID)
|
||||
},
|
||||
|
||||
@@ -96,6 +96,7 @@ struct PlayerControlsView: View {
|
||||
var embeddedSubtitleTracks: [MPVTrack] = []
|
||||
var currentEmbeddedAudioTrackID: Int? = nil
|
||||
var currentEmbeddedSubtitleTrackID: Int? = nil
|
||||
var embeddedVideoTrack: MPVTrack? = nil
|
||||
/// Callback when an embedded audio track is selected
|
||||
var onEmbeddedAudioTrackSelected: ((Int) -> Void)? = nil
|
||||
/// Callback when an embedded subtitle track is selected (nil = off)
|
||||
@@ -315,6 +316,7 @@ struct PlayerControlsView: View {
|
||||
currentAudioStream: currentAudioStream,
|
||||
initialTab: .video,
|
||||
showTabPicker: false,
|
||||
embeddedVideoTrack: embeddedVideoTrack,
|
||||
onStreamSelected: { stream, audioStream in
|
||||
onStreamSelected?(stream, audioStream)
|
||||
},
|
||||
|
||||
@@ -184,7 +184,7 @@ extension QualitySelectorView {
|
||||
if format == .hls || format == .dash {
|
||||
return format == .hls ? "HLS" : "DASH"
|
||||
}
|
||||
return stream.qualityLabel
|
||||
return displayStream(for: stream).qualityLabel
|
||||
}
|
||||
|
||||
private var currentAudioDisplayValue: String {
|
||||
@@ -695,6 +695,35 @@ extension QualitySelectorView {
|
||||
}
|
||||
}
|
||||
|
||||
/// A local file's Stream carries no resolution/codec/fps metadata
|
||||
/// (`MediaFile.toStream` cannot know them before demux), which would label
|
||||
/// the row "Unknown". Once mpv reports the file's video track, fill those
|
||||
/// fields for display. The enriched copy is display-only — selection and
|
||||
/// tap handling keep using the original stream (compared by URL).
|
||||
func displayStream(for stream: Stream) -> Stream {
|
||||
guard stream.url.isFileURL,
|
||||
stream.resolution == nil,
|
||||
!stream.isAudioOnly,
|
||||
let track = embeddedVideoTrack,
|
||||
let width = track.width,
|
||||
let height = track.height else {
|
||||
return stream
|
||||
}
|
||||
return Stream(
|
||||
url: stream.url,
|
||||
resolution: StreamResolution(width: width, height: height),
|
||||
format: stream.format,
|
||||
videoCodec: track.codec ?? stream.videoCodec,
|
||||
audioCodec: stream.audioCodec,
|
||||
bitrate: stream.bitrate,
|
||||
fileSize: stream.fileSize,
|
||||
isLive: stream.isLive,
|
||||
mimeType: stream.mimeType,
|
||||
httpHeaders: stream.httpHeaders,
|
||||
fps: track.fps.map { Int($0.rounded()) }
|
||||
)
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func videoStreamRow(_ stream: Stream) -> some View {
|
||||
let isDownloadedStream: Bool = stream.url.isFileURL
|
||||
@@ -704,7 +733,7 @@ extension QualitySelectorView {
|
||||
let isPreferredQuality: Bool = stream.resolution == preferredQuality.maxResolution
|
||||
|
||||
VideoStreamRowView(
|
||||
stream: stream,
|
||||
stream: displayStream(for: stream),
|
||||
isSelected: isSelected,
|
||||
isPreferredQuality: isPreferredQuality,
|
||||
isDownloaded: isDownloadedStream,
|
||||
|
||||
@@ -34,6 +34,8 @@ struct QualitySelectorView: View {
|
||||
let embeddedSubtitleTracks: [MPVTrack]
|
||||
let currentEmbeddedAudioTrackID: Int?
|
||||
let currentEmbeddedSubtitleTrackID: Int?
|
||||
/// The playing file's video track, used to label metadata-less local streams
|
||||
let embeddedVideoTrack: MPVTrack?
|
||||
let onEmbeddedAudioTrackSelected: (Int) -> Void
|
||||
/// nil = subtitles off
|
||||
let onEmbeddedSubtitleTrackSelected: (Int?) -> Void
|
||||
@@ -181,6 +183,7 @@ struct QualitySelectorView: View {
|
||||
embeddedSubtitleTracks: [MPVTrack] = [],
|
||||
currentEmbeddedAudioTrackID: Int? = nil,
|
||||
currentEmbeddedSubtitleTrackID: Int? = nil,
|
||||
embeddedVideoTrack: MPVTrack? = nil,
|
||||
onStreamSelected: @escaping (Stream, Stream?) -> Void,
|
||||
onCaptionSelected: @escaping (Caption?) -> Void = { _ in },
|
||||
onLoadOnlineStreams: @escaping () -> Void = {},
|
||||
@@ -210,6 +213,7 @@ struct QualitySelectorView: View {
|
||||
self.embeddedSubtitleTracks = embeddedSubtitleTracks
|
||||
self.currentEmbeddedAudioTrackID = currentEmbeddedAudioTrackID
|
||||
self.currentEmbeddedSubtitleTrackID = currentEmbeddedSubtitleTrackID
|
||||
self.embeddedVideoTrack = embeddedVideoTrack
|
||||
self.onStreamSelected = onStreamSelected
|
||||
self.onCaptionSelected = onCaptionSelected
|
||||
self.onLoadOnlineStreams = onLoadOnlineStreams
|
||||
|
||||
@@ -171,6 +171,7 @@ struct TVPlayerView: View {
|
||||
embeddedSubtitleTracks: playerService.embeddedSubtitleTracks,
|
||||
currentEmbeddedAudioTrackID: playerService.selectedEmbeddedAudioTrackID,
|
||||
currentEmbeddedSubtitleTrackID: playerService.selectedEmbeddedSubtitleTrackID,
|
||||
embeddedVideoTrack: playerService.primaryEmbeddedVideoTrack,
|
||||
onStreamSelected: { stream, audioStream in
|
||||
switchToStream(stream, audioStream: audioStream)
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user