sách gpt4 ăn đã đi

AVPlayer có phụ đề được tải sẵn bị hỏng khi ",SUBTITLES=\"subs\"" được thêm vào cuối dòng "#EXT-X-STREAM-INF:"( AVPlayer có "#EXT-X-STREAM-INF: " dòng được thêm vào cuối có phụ đề được tải sẵn bị hỏng trong: ",SUBTITES=\"SUBS\"")

In lại Tác giả: trợ lý lỗi Thời gian cập nhật: 25-10-2023 12:04:32 42 4
mua khóa gpt4 giày nike



Tôi đang sử dụng phiên bản đã sửa đổi của đại biểu của kanderson-wellbeats để sửa đổi các yêu cầu khi AVKit cần chúng. Tất cả các mã sẽ ở cuối bài đăng. Mọi thứ đều ổn khi sửa đổi các yêu cầu, tạo danh sách phát phụ đề và thêm chúng vào danh sách phát chính khi chúng hiển thị khi yêu cầu AVMediaĐặc điểm.có thể đọc được, nhưng ngay khi tôi thêm dòng thêm ",SUBTITLES="subs"" vào cuối các dòng "#EXT-X-STREAM-INF:", dòng này sẽ thêm phụ đề vào track video đó, thì video sẽ không phát nữa. Xóa phần đó giúp có thể chọn track phụ đề trên playerItem, nhưng phụ đề không hiển thị trên màn hình.

Tôi đang sử dụng phiên bản sửa đổi của đại biểu nhịp đập kanderson-well để sửa đổi các yêu cầu mà AVKit cần. Tất cả mã sẽ ở dưới cùng của bài viết. Bạn nên sửa đổi yêu cầu, tạo danh sách phát phụ đề và thêm chúng vào danh sách phát chính vì chúng sẽ được hiển thị khi AVMediaCharacteristic được yêu cầu. Tuy nhiên, ngay sau khi tôi thêm dòng ",Subtiles="subtiles="subs" vào cuối dòng "#ext-X-stream-INF:", nó sẽ không phát nữa, điều này sẽ thêm phụ đề vào đoạn video đó. Việc bỏ phần này giúp bạn có thể chọn track phụ đề trên playerItem nhưng phụ đề sẽ không hiển thị trên màn hình.


Lưu ý rằng tôi đang sử dụng AVPlayer tùy chỉnh với AVPlayerLayer thay vì AVPlayerViewController vì tôi cần tùy chỉnh nhiều hơn; có thể đó là vấn đề?

Lưu ý rằng tôi đang sử dụng AVPlayer tùy chỉnh với AVPlayerLayer thay vì AVPlayerViewController vì tôi cần tùy chỉnh nhiều hơn, có lẽ đó là vấn đề?


Tôi biết có lẽ tôi chỉ cần thêm lớp phủ với UILabel cho phụ đề, nhưng tôi muốn giải pháp mang tính bản địa hơn.

Tôi biết có lẽ tôi chỉ cần thêm lớp phủ có UILabel cho phụ đề, nhưng tôi muốn giải pháp mang tính địa phương hơn.


InterceptingAssetResourceLoaderDelegate.swift

Lưu ý: trong danh sách phụ đề ở đây, không có dấu phẩy ở cuối dòng "#EXTINF:(rounded)". Có vẻ như không có thay đổi nào về việc thêm hay không, nhưng kanderson-wellbeats cho biết việc thêm nó sẽ gây ra sự cố, vì vậy nó đã bị xóa ngay bây giờ.

Lưu ý: Trong danh sách phụ đề ở đây không có dấu phẩy ở cuối dòng "#EXTINF: (làm tròn)". Việc thêm hay không thêm nó dường như không tạo ra sự khác biệt, nhưng Kanderson-Well Beats cho biết việc thêm nó sẽ gây ra vấn đề nên hiện tại nó đã bị xóa.


nhập AVKit

lớp InterceptingAssetResourceLoaderDelegate: NSObject, AVAssetResourceLoaderDelegate {
lớp riêng SubtitleBundle {
init nội bộ (subtitleDTO: InterceptingAssetResourceLoaderDelegate.SubtitleDTO, danh sách phát: String? = nil) {
self.subtitleDTO = phụ đềDTO
self.playlist = danh sách phát
}

hãy để phụ đềDTO: SubtitleDTO
danh sách phát là: Chuỗi?
}

cấu trúc riêng tư SubtitleDTO {
cho ngôn ngữ: Chuỗi
hãy để tiêu đề: Chuỗi
cho url: Chuỗi
}

static let videoUrlPrefix = "VIDEO BỊ CHẶN"
tĩnh cho subtitleUrlPrefix = "Tiêu đề bị chặn"
tĩnh cho subtitleUrlSuffix = "m3u8"
phiên riêng tư cho phép: URLSession
riêng tư cho subtitleBundles: [SubtitleBundle]

init(_ phụ đề: [VideoSourceEpisodeUrlSubtitle]) {
self.session = URLSession(cấu hình: .default)
self.subtitleBundles = phụ đề.map({
SubtitleBundle(subtitleDTO: SubtitleDTO(ngôn ngữ: $0.language, tiêu đề: $0.name, url: $0.url))
})
}

hàm resourceLoader(
_ resourceLoader: AVAssetResourceLoader,
shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest
) -> Bool {
bảo vệ cho url = loadingRequest.request.url,
hãy để dataRequest = loadingRequest.dataRequest nếu không { trả về true }

nếu url.absoluteString.starts(với: Self.subtitleUrlPrefix) {
bảo vệ let targetLanguage = url.host?.split(separator: ".").đầu tiên,
hãy để targetSubtitle = self.subtitleBundles.first(trong đó: { $0.subtitleDTO.language == targetLanguage }),
hãy để subtitleUrl = URL(chuỗi: targetSubtitle.subtitleDTO.url) nếu không {
loadingRequest.finishLoading(với: AVError(.unknown))
trả về đúng
}

hãy để subtitlePlaylistTask = self.session.dataTask(with: subtitleUrl) { [weak self] dữ liệu, _, lỗi trong
nếu để lỗi {
loadingRequest.finishLoading(với: lỗi)
trở lại
}
bảo vệ cho dữ liệu, !data.isEmpty, cho dataString = String(dữ liệu: dữ liệu, mã hóa: .utf8) else {
loadingRequest.finishLoading(với: AVError(.unknown))
trở lại
}

self?.makePlaylistAndFragments(bundle: targetSubtitle, subtitle: dataString)

bảo vệ let playlistData = targetSubtitle.playlist?.data(sử dụng: .utf8) else {
loadingRequest.finishLoading(với: AVError(.unknown))
trở lại
}
dataRequest.respond(với: playlistData)
}

phụ đềPlaylistTask.resume()
trả về đúng
}

bảo vệ let newUrl = URL(chuỗi: url.absoluteString.replacingOccurrences(của: Self.videoUrlPrefix, với: "")) nếu không { trả về đúng }

nếu như !(
url.absoluteString.lowercased().hasSuffix(".ism/manifest(format=m3u8-aapl)") ||
url.absoluteString.lowercased().hasSuffix(".m3u8")
) || (
dataRequest.requestedOffset == 0 && dataRequest.requestedLength == 2 && dataRequest.currentOffset == 0
) {
hãy để newRequest = URLRequest(url: newUrl)
loadingRequest.redirect = Yêu cầu mới
hãy để fakeResponse = HTTPURLResponse(url: newUrl, statusCode: 302, httpVersion: nil, headerFields: nil)
loadingRequest.response = fakeResponse
loadingRequest.kết thúc việc tải()
trả về đúng
}

var editedRequest = URLRequest(url: newUrl)
cho tiêu đề trong loadingRequest.request.allHTTPHeaderFields ?? [:] {
editedRequest.addValue(header.value, forHTTPHeaderField: header.key)
}

hãy để masterPlaylistTask = self.session.dataTask(with: correctedRequest) { [weak self] dữ liệu, _, lỗi trong
nếu để lỗi {
loadingRequest.finishLoading(với: lỗi)
trở lại
}

bảo vệ dữ liệu,
hãy để dataString = String(dữ liệu: dữ liệu, mã hóa: .utf8),
hãy để withSubs = self?.addSubs(đến: dataString),
hãy để withSubsData = withSubs.data(sử dụng: .utf8) nếu không {
loadingRequest.finishLoading(với: AVError(.unknown))
trở lại
}
dataRequest.respond(với: withSubsData)
loadingRequest.kết thúc việc tải()
}
masterPlaylistTask.resume()
trả về đúng
}

hàm addSubs(đến dataString: String) -> String {
bảo vệ dataString.contains("#EXT-X-STREAM-INF:") nếu không { trả về dataString }
var tracks = dataString.split(dấu phân cách: "\n").map({ $0.hasPrefix("#EXT-X-STREAM-INF:") ? $0 + ",SUBTITLES=\"subs\"" : $0 })
track.insert(nội dung của: subtitleBundles.map({
"#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",LANGUAGE=\"\($0.subtitleDTO.language)\",NAME=\"\($0.subtitleDTO.title)\","
+ "AUTOSELECT=YES,URI=\"\(Self.subtitleUrlPrefix)://\($0.subtitleDTO.language).\(Self.subtitleUrlSuffix)\""
}), tại: tracks.firstIndex(nơi: { $0.contains("#EXT-X-STREAM-INF") }) ?? tracks.endIndex)
trả về tracks.joined(separator: "\n")
}

hàm riêng makePlaylistAndFragments(bundle: SubtitleBundle, subtitle: String) {
nếu cho regex = thử? NSRegularExpression(mẫu: #"(\d{2}:\d{2}:\d{2}.\d{3})"#),
hãy để timeString = regex.matches(trong: phụ đề, phạm vi: NSRange(vị trí: 0, độ dài: phụ đề.count)).last.flatMap({
(phụ đề là NSString).substring(với: $0.range)
}),
hãy để giờ = timeString.split(dấu phân cách: ":")[safe: 0].flatMap({ Double($0) }), giờ.isFinite,
cho phút = timeString.split(separator: ":")[safe: 1].flatMap({ Double($0) }), phút.isFinite,
hãy để giây = timeString.split(dấu phân cách: ":")[an toàn: 2].flatMap({ Double($0) }), giây.isFinite {
let rounded = Int(ceil(giờ * 3600 + phút * 60 + giây))
bundle.playlist = [
"#EXTM3U",
"#EXT-X-TARGETDURATION:\(làm tròn)",
"#EXT-X-VERSION:3",
"#EXT-X-MEDIA-SEQUENCE:0",
"#EXT-X-PLAYLIST-TYPE:VOD",
"#EXTINF:\(làm tròn)",
bundle.subtitleDTO.url,
"#EXT-X-ENDLIST"
].joined(dấu phân cách: "\n")
} else if let regex = try? NSRegularExpression(mẫu: #"(\d{2}:\d{2}.\d{3})"#),
hãy để timeString = regex.matches(trong: phụ đề, phạm vi: NSRange(vị trí: 0, độ dài: phụ đề.count)).last.flatMap({
(phụ đề là NSString).substring(với: $0.range)
}),
để phút = timeString.split(separator: ":")[safe: 0].flatMap({ Double($0) }), phút.isFinite,
hãy để giây = timeString.split(dấu phân cách: ":")[an toàn: 1].flatMap({ Double($0) }), giây.isFinite {
let rounded = Int(ceil(phút * 60 + giây))
bundle.playlist = [
"#EXTM3U",
"#EXT-X-TARGETDURATION:\(làm tròn)",
"#EXT-X-VERSION:3",
"#EXT-X-MEDIA-SEQUENCE:0",
"#EXT-X-PLAYLIST-TYPE:VOD",
"#EXTINF:\(làm tròn)",
bundle.subtitleDTO.url,
"#EXT-X-ENDLIST"
].joined(dấu phân cách: "\n")
}
}
}

VideoPlayerViewController.swift

VideoPlayerViewController.swift


    func setSubtitles(đến phụ đề: [VideoSourceEpisodeUrlSubtitle]) {
Nhiệm vụ {
nếu let group = try? chờ self.playerLayer.player?.currentItem?.asset.loadMediaSelectionGroup(
cho: AVMediaCharacteristic.legible
) {
self.captionsButton.menu = UIMenu(con: [
Hành động UI(
tiêu đề: "Không có",
hình ảnh: self.currentSubtitleTrack == nil ? UIImage(systemName: "checkmark") : nil
) { [bản thân yếu đuối] _ trong
self?.playerLayer.player?.currentItem?.select(nil, trong: nhóm)
self?.currentSubtitleTrack = nil
self?.setSubtitles(đến: phụ đề)
}
] + subtitles.map({ phụ đề trong
Hành động UI(
tiêu đề: subtitle.name,
hình ảnh: self.currentSubtitleTrack?.url == subtitle.url ? UIImage(systemName: "checkmark") : nil
) { [bản thân yếu đuối] _ trong
hãy để tùy chọn = AVMediaSelectionGroup.mediaSelectionOptions(từ: group.options, với: Locale(
định danh: subtitle.language
))
nếu let option = options.first {
self?.playerLayer.player?.currentItem?.select(tùy chọn, trong: nhóm)
self?.currentSubtitleTrack = phụ đề
self?.setSubtitles(đến: phụ đề)
}
}
}))
}
}
}

VideoSourceEpisodeUrlSubtitle.swift

VideoSourceEpisodeUrlSubtitle.swift


struct VideoSourceEpisodeUrlSubtitle: Codable {
hãy đặt tên: Chuỗi
cho url: Chuỗi
cho ngôn ngữ: Chuỗi
}

Cảm ơn mọi người trước vì sự giúp đỡ.

Cảm ơn trước vì tất cả sự giúp đỡ của bạn.


Thêm câu trả lời
Khuyến nghị câu trả lời tuyệt vời
Thêm câu trả lời
42 4 0
trợ lý lỗi
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress