CC support with Invidious and MPV

This commit is contained in:
Arkadiusz Fal
2022-07-05 19:20:25 +02:00
parent 3718311a93
commit e56ab3804e
11 changed files with 163 additions and 25 deletions

View File

@@ -428,7 +428,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
keywords: json["keywords"].arrayValue.compactMap { $0.string },
streams: extractStreams(from: json),
related: extractRelated(from: json),
chapters: extractChapters(from: description)
chapters: extractChapters(from: description),
captions: extractCaptions(from: json)
)
}
@@ -566,4 +567,17 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
channel: Channel(id: channelId, name: author)
)
}
private func extractCaptions(from content: JSON) -> [Captions] {
content["captions"].arrayValue.compactMap { details in
guard let baseURL = account.url,
let url = URL(string: baseURL + details["url"].stringValue) else { return nil }
return Captions(
label: details["label"].stringValue,
code: details["language_code"].stringValue,
url: url
)
}
}
}

12
Model/Captions.swift Normal file
View File

@@ -0,0 +1,12 @@
import Foundation
struct Captions: Hashable, Identifiable {
var id = UUID().uuidString
let label: String
let code: String
let url: URL
var description: String {
"\(label) (\(code))"
}
}

View File

@@ -19,6 +19,13 @@ final class MPVBackend: PlayerBackend {
var stream: Stream?
var video: Video?
var captions: Captions? { didSet {
guard let captions = captions else {
client.removeSubs()
return
}
addSubTrack(captions.url)
}}
var currentTime: CMTime?
var loadedVideo = false
@@ -155,11 +162,18 @@ final class MPVBackend: PlayerBackend {
}
#endif
var captions: Captions?
if let captionsLanguageCode = Defaults[.captionsLanguageCode] {
captions = video.captions.first { $0.code == captionsLanguageCode } ??
video.captions.first { $0.code.contains(captionsLanguageCode) }
}
let updateCurrentStream = {
DispatchQueue.main.async { [weak self] in
self?.stream = stream
self?.video = video
self?.model.stream = stream
self?.captions = captions
}
}
@@ -211,7 +225,7 @@ final class MPVBackend: PlayerBackend {
startPlaying()
}
self.client.loadFile(url, time: time) { [weak self] _ in
self.client.loadFile(url, sub: captions?.url, time: time) { [weak self] _ in
self?.isLoadingVideo = true
}
} else {
@@ -223,7 +237,7 @@ final class MPVBackend: PlayerBackend {
let fileToLoad = self.model.musicMode ? stream.audioAsset.url : stream.videoAsset.url
let audioTrack = self.model.musicMode ? nil : stream.audioAsset.url
self.client?.loadFile(fileToLoad, audio: audioTrack, time: time) { [weak self] _ in
self.client?.loadFile(fileToLoad, audio: audioTrack, sub: captions?.url, time: time) { [weak self] _ in
self?.isLoadingVideo = true
self?.pause()
}
@@ -454,6 +468,11 @@ final class MPVBackend: PlayerBackend {
client?.addVideoTrack(url)
}
func addSubTrack(_ url: URL) {
client?.removeSubs()
client?.addSubTrack(url)
}
func setVideoToAuto() {
client?.setVideoToAuto()
}

View File

@@ -110,7 +110,7 @@ final class MPVClient: ObservableObject {
}
}
func loadFile(_ url: URL, audio: URL? = nil, time: CMTime? = nil, completionHandler: ((Int32) -> Void)? = nil) {
func loadFile(_ url: URL, audio: URL? = nil, sub: URL? = nil, time: CMTime? = nil, completionHandler: ((Int32) -> Void)? = nil) {
var args = [url.absoluteString]
var options = [String]()
@@ -123,6 +123,10 @@ final class MPVClient: ObservableObject {
options.append("audio-files-append=\"\(audioURL)\"")
}
if let subURL = sub?.absoluteString {
options.append("sub-files-append=\"\(subURL)\"")
}
args.append(options.joined(separator: ","))
command("loadfile", args: args, returnValueCallback: completionHandler)
@@ -263,6 +267,14 @@ final class MPVClient: ObservableObject {
command("video-add", args: [url.absoluteString])
}
func addSubTrack(_ url: URL) {
command("sub-add", args: [url.absoluteString])
}
func removeSubs() {
command("sub-remove")
}
func setVideoToAuto() {
setString("video", "1")
}

View File

@@ -47,6 +47,11 @@ final class PlayerControlsModel: ObservableObject {
func handleOverlayPresentationChange() {
player?.backend.setNeedsNetworkStateUpdates(presentingControlsOverlay)
if presentingControlsOverlay {
removeTimer()
} else {
resetTimer()
}
}
func show() {

View File

@@ -34,6 +34,8 @@ struct Video: Identifiable, Equatable, Hashable {
var related = [Video]()
var chapters = [Chapter]()
var captions = [Captions]()
init(
id: String? = nil,
videoID: String,
@@ -55,7 +57,8 @@ struct Video: Identifiable, Equatable, Hashable {
keywords: [String] = [],
streams: [Stream] = [],
related: [Video] = [],
chapters: [Chapter] = []
chapters: [Chapter] = [],
captions: [Captions] = []
) {
self.id = id ?? UUID().uuidString
self.videoID = videoID
@@ -78,6 +81,7 @@ struct Video: Identifiable, Equatable, Hashable {
self.streams = streams
self.related = related
self.chapters = chapters
self.captions = captions
}
var publishedDate: String? {