Hi Apple Team, we are observing following error intermittently when trying to playback FairPlay protected HLS streams. The error happens immediately after loading the certificate.
Playback with same certificate on same device(Mac, iPhone) works most of time but intermittently this error is observed with following codes. The code=6 means MEDIA_KEYERR_DOMAIN but I did not find any information on what does systemCode=4294955417 mean? Is there a way to check what does this system code mean and what could be causing this intermittent behaviour?
{
"code": 6,
"systemCode": 4294955417
}
Streaming
RSS for tagDeep dive into the technical specifications that influence seamless playback for streaming services, including bitrates, codecs, and caching mechanisms.
Post
Replies
Boosts
Views
Activity
I have a VisionOS app that streams 180VR video to create immersive experiences, similar to the Apple TV+ immersive content. These videos are 8k60fps. When looking at "video encoding requirements" (1.25) in the hls authoring specifications, there are only specifications for up to 4k30fps for MV-HEVC. Using the "power of .75 rule" I think that 160000kbps could be close to the 8k60fps recommendation.
For launching my app, I did my best guess in creating the following multivariant playlist, with a generous low end and very generous high end, with 6 second segment durations for all variants. However, in practice, users seem to be to only be picking up the lower quality bandwidth content (80000kbps) even when speed tests are showing 5x that on the device. This leads to a lot artifacts in the content during playback, since its lower quality. If I hard code a higher bit rate variant (like 240000kbps) it does playback, but obviously has a bit more lag to start up.
Now that I have my Vision Pro, I've been able to see the Apple TV+ immersive content. I could be wrong, but it doesn't feel like its varying playback - when watch by tethering to my phone vs on high speed wifi, the content looks the same just a little slower to load on the phone.
I'm looking for 3 points of guidance:
Are there hls recommendations for 8k60fps video? For both bitrates and target duration for the segments?
Any guesses as to why I am not able to pick up the high bitrates? (this could simply be that the higher ends are still too high)
While 180VR is just stereo video on a larger canvas, the viewing experience is quite different due to the immersion. Are there special recommendations for 180VR video? (Such as having only one variant and specified bitrate since a changing bitrate/video quality could be jarring to the viewer)
Example HLS multivariant playlist:
#EXTM3U
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=80632574,BANDWIDTH=82034658,VIDEO-RANGE=SDR,CODECS="mp4a.40.2,hvc1.1.60000000.L183.B0",RESOLUTION=4096x4096,FRAME-RATE=59.940,CLOSED-CAPTIONS=NONE
https://myurl.com/stream/t4096p_080000_kbps_t6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=160782750,BANDWIDTH=162523567,VIDEO-RANGE=SDR,CODECS="mp4a.40.2,hvc1.1.60000000.L186.B0",RESOLUTION=4096x4096,FRAME-RATE=59.940,CLOSED-CAPTIONS=NONE
https://myurl.com/stream/t4096p_160000_kbps_t6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=240941602,BANDWIDTH=243997537,VIDEO-RANGE=SDR,CODECS="mp4a.40.2,hvc1.1.60000000.L186.B0",RESOLUTION=4096x4096,FRAME-RATE=59.940,CLOSED-CAPTIONS=NONE
https://myurl.com/stream/t4096p_240000_kbps_t6/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=321061516,BANDWIDTH=325312545,VIDEO-RANGE=SDR,CODECS="mp4a.40.2,hvc1.1.60000000.H255.B0",RESOLUTION=4096x4096,FRAME-RATE=59.940,CLOSED-CAPTIONS=NONE
https://myurl.com/stream/t4096p_320000_kbps_t6/prog_index.m3u8
Mediastreamvalidiator error:
all .m3u8 files relevant have already the REQ-VIDEO-LAYOUT="CH-STEREO" parameter set.
Nevertheless mediastreamvalidator check/reports for HLS Authoring Specification for Apple Devices states:
General requirements
Must Fix Issues
You MUST declare REQ-VIDEO-LAYOUT for variants containing other then standard monoscopic video
Variant #1
Dear Apple Engineers,
I have downloaded the FairPlay Streaming SDK 4.4 - In which i could able to make use of the fps_safari_hls_example.html file to make a successful playback of fairplay protected content in safari, by pointing our fairplay license server, .m3u8 file & certificate.
Now that, i'm trying to achieve the renewal concept, so i tried to use the fps_safari_hls_key_renewal.html file also setting up the ContentKeyDuration to 20sec in FP license server backend. But client didn't make any subsequent FP license request around when nearing 20th sec or post 20th sec. I wonder if this use case be achieved in safari,
the only extra functionality i could see in renewal html file is below piece of code
await runAndWaitForLicenseRequest(session, keyURI, () => {
session.update(stringToUInt8Array("renew"))
});
Based on the above piece, i assume that we are making sure that client to aware the when to renew the license. But in my case, there were no FP request is made , in-fact, this piece of code got executed immediate after the 1st FP license request call & protected media continues to play despite setting the ContentKeyDuration to 20sec with LIMITED as contentkeyType .
Could you please suggest on how to achieve the subsequent renewal request from client based on the ContentKeyDuration send in the CKC response using this sample renewal html file..? Is there any tewaks to be made in html file, kindly suggest.
We are aiming to apply KeyRotation for FPS service for our content streaming service.
It is not clear from the spécifications how "FairPlay Streaming Programming Guide.pdf" How to apply this feature and let the "FPS DRM key server KSM " send multiple-keys at a time in one licence :(CKC) in the key rotation moment. without using the Renting and Leasing key features.
Note that we don't use Offline Playback capabilities for our streams.
Error message preventing html generation: hlsreport[25380:1522553] read JSON failed.
Used v1.22
Error persists.
Hello there,
I understand most components of the FairPlay Streaming Server SDK haven't been updated in about a decade, but the verify_ckc tool no longer works, and it's really helpful. It throws errors when trying to import the Crypto library...probably something to do with this whole Python 2 vs Python 3 thing.
I don't know anything about Python or I'd try to fix it myself but...I'm just bringing this up in case anyone from the FairPlay team reads these things!
Thx
Hi
I am trying to implement D Function in python.
import hashlib
from Crypto.Cipher import AES
from Crypto.Hash import SHA
from Crypto.Util.Padding import pad as padding
from Crypto.PublicKey import RSA
PRIME = 813416437
NB_RD = 16
def dfunction(R2, ASk):
tmp = bytearray(20)
pad = bytearray(64)
MBlock = [0] * 14
P = PRIME
if len(R2) >= 56:
return -1 # kDRMSKDServerParamErr
# Padding until a multiple of 56B
pad[:len(R2)] = R2
pad[len(R2)] = 0x80
pad[len(R2) + 1:56] = [0] * (56 - len(R2) - 1)
# Create 14 32b values
for i in range(14):
MBlock[i] = (pad[4 * i] << 24) ^ (pad[4 * i + 1] << 16) ^ (pad[4 * i + 2] << 8) ^ pad[4 * i + 3]
# Reunify into 2 32 bits values
#MBlock[0] += sum(MBlock[1:7])
#MBlock[1] = 0
#MBlock[1] += sum(MBlock[7:])
# Reunify into 2 32 bits values
for i in range(1, 7):
MBlock[0] += MBlock[i]
MBlock[1] = 0
for i in range(7):
MBlock[1] += MBlock[i + 7]
# Apply the function (C_r)
for i in range(2):
for r in range(NB_RD):
if MBlock[i] & 1:
MBlock[i] >>= 1
else:
MBlock[i] = (3 * MBlock[i] + 1) % P
# Append to M
for i in range(4):
pad[56 + i] = (MBlock[0] >> (8 * i)) & 0xFF
pad[60 + i] = (MBlock[1] >> (8 * i)) & 0xFF
h = hashlib.sha1()
h.update(pad)
hh = h.digest()[:16]
cipher = AES.new(ASk, AES.MODE_ECB)
DASk = cipher.encrypt(padding(hh, AES.block_size))
return DASk
Then, i am trying to match integrities and they does not match. I think there is an mistake in D Function implementation. Any clue whats wrong?
Thank you
Hi
I was wondering if there any D Function implementations on Python to derive dASK?
Thank you
Hello,
I keep getting this kind of errors (specifically 16247) when trying to download DRM-protected HLS content, would anyone have a clue about the reason why ?
Error Domain=CoreMediaErrorDomain Code=-16247 "(null)" UserInfo={_NSURLErrorRelatedURLSessionTaskErrorKey=("BackgroundAVAssetDownloadTask
Thanks
Sylvain
how to use AIGC in the workplace to assist with work?
Per FP Streaming programming guide,
The SPC includes a specific TLLV to provide the state of the media content playback. And total value length of this is 16 in decimals.
Here i'm trying to retrieve the Playback State. which is of 20-23 ByteRange.
byte[] mediaPlaybackStateBlock = getBlock(MEDIA_PLAYBACK_STATE).getValueData();
playbackState = Arrays.copyOfRange(mediaPlaybackStateBlock, 20, 24);
I'm endup in issue - arraycopy: length -4 is negative.
I'm bit confused on how to retrieve the playback state from 20-23 ByteRange when its length jus 16..
Kindly clarify
Since iOS 17.2. the video player in Safari becomes black if I jump forward in a HLS video stream. I only hear the sound of the video. If I close the full screen and reopen it the video continious normally.
I checked if the source meets all the requirements mentioned here and it does.
Does anybody have the same issue or maybe a solution for this problem?
Hello all,
I am a completely new to iOS development, and I need to make an app that will be playing encrypted content using Fairplay. Right now I am using the Sample client in the latest FPS Server SDK (HLSCatalog), and from what I understand the default sources in Streams.plist are not protected. There's an entry with is_protected=YES and where I can replace the playlist_url, but I was wondering if I could use the .m3u8 files in the FPS Test Content found at https://developer.apple.com/streaming/fps/ ? If so, I don't really know how to.
In one of the .m3u8 files of the Test Content, I could find the "content_key_id_list" example value that's also mentioned in the client's README (skd://twelve), which is why I'm asking.
Thanks in advance!
Hi Team,
We see an issue with this version if CoreMedia requesting multiple qualities at all times for a stream. We don't see this issue on 1.0.0.21C62. We are unsure what would be causing this.
[2024-01-05 16:53:51] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=0 HTTP/1.0" 200 1145 2529 1090199 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=0 HTTP/1.0" 200 1146 2396 1013356 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_0.fmp4 HTTP/1.0" 200 1139 24975 1013385 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=1 HTTP/1.0" 200 1145 2603 998670 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:52] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_1.fmp4 HTTP/1.0" 200 1138 40534 998739 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=2 HTTP/1.0" 200 1145 2677 835327 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_2.fmp4 HTTP/1.0" 200 1138 57656 835207 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=1 HTTP/1.0" 200 1146 2458 986038 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:53] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_1.fmp4 HTTP/1.0" 200 1139 24700 986032 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=3 HTTP/1.0" 200 1145 2751 1013257 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_3.fmp4 HTTP/1.0" 200 1138 55900 1013324 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=2 HTTP/1.0" 200 1146 2520 1016693 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:54] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_2.fmp4 HTTP/1.0" 200 1139 25014 1016717 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=4 HTTP/1.0" 200 1145 2825 917753 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_4.fmp4 HTTP/1.0" 200 1138 103745 917903 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=3 HTTP/1.0" 200 1146 2582 958102 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:55] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_3.fmp4 HTTP/1.0" 200 1139 24782 958195 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=630&_HLS_part=5 HTTP/1.0" 200 1145 2899 931101 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_720p/v_1058_2452140000_630_5.fmp4 HTTP/1.0" 200 1138 112113 931228 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=4 HTTP/1.0" 200 1146 2644 935550 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:56] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_4.fmp4 HTTP/1.0" 200 1139 24824 937720 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_1080p/audio.m3u8?_HLS_msn=630&_HLS_part=5 HTTP/1.0" 200 1146 2706 895680 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_1080p/a_1459_2452140264_630_5.fmp4 HTTP/1.0" 200 1139 24843 895734 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
[2024-01-05 16:53:57] "GET /live/cinecanal/live/cinecanal_720p/video.m3u8?_HLS_msn=631&_HLS_part=0 HTTP/1.0" 200 1145 2529 907045 "-" "AppleCoreMedia/1.0.0.21B101 (iPhone; U; CPU OS 17_1_2 like Mac OS X; en_us)"
The error shown in the picture appears when I try to link the StartScene.sks file to the code
Attached are pictures of the code
Please help me🙏🏻
I'm trying to use AVCaptureSession and AVAssetWriter to convert video and audio from an iPhone's camera and microphone into a fragmented video file in AppleHLS format.
Below is part of the code.
It seems that the capture is successful, and I have confirmed that the data received with captureOutput() can be appended to videoWriterIput and audioWriterInput using append().
When executing audioWriterInput!.append(sampleBuffer), sampleBuffer has the following value, and it looks like the audio data has been passed to AssetWriter.
sampleBuffer.duration : CMTime(value: 941, timescale: 44100, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
sampleBuffer.totalSampleSize : 1882
However, the final output init.mp4 and *.m4s do not contain Audio. (The video can be played without any problems.)
Could you please tell me any problems or hints as to why Audio is not included?
/// Capture Session
let captureSession = AVCaptureSession()
/// Capture Input
var videoDevice: AVCaptureDevice?
var audioDevice: AVCaptureDevice?
/// Configure and Start Capture Session
func startCapture() {
// Start Configuration
captureSession.beginConfiguration()
// Setup Input Video
videoDevice = self.defaultCamera(cameraSide: cameraSide)
videoDevice!.activeVideoMinFrameDuration = CMTimeMake(value: 1, timescale: 30)
let videoInput = try AVCaptureDeviceInput(device: videoDevice!) as AVCaptureDeviceInput
captureSession.addInput(videoInput)
// Setup Input Audio
audioDevice = AVCaptureDevice.default(for: AVMediaType.audio)
let audioInput = try AVCaptureDeviceInput(device: audioDevice!) as AVCaptureDeviceInput
captureSession.addInput(audioInput)
// Setup Output Video
let videoDataOutput = AVCaptureVideoDataOutput()
videoDataOutput.setSampleBufferDelegate(self, queue: recordingQueue)
videoDataOutput.alwaysDiscardsLateVideoFrames = true
videoDataOutput.videoSettings = [
kCVPixelBufferPixelFormatTypeKey: Int(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)] as [String : Any]
captureSession.addOutput(videoDataOutput)
// Setup Output Audio
let audioDataOutput = AVCaptureAudioDataOutput()
audioDataOutput.setSampleBufferDelegate(self, queue: recordingQueue)
captureSession.addOutput(audioDataOutput)
//End Configuration
captureSession.commitConfiguration()
// Start Capture
captureSession.startRunning()
}
private let assetWriter: AVAssetWriter?
private let startTimeOffset: CMTime
private var audioWriterInput: AVAssetWriterInput?
private let videoWriterInput: AVAssetWriterInput?
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
if assetWriter == nil {
// AssetWriter
assetWriter = AVAssetWriter(contentType: UTType(AVFileType.mp4.rawValue)!)
self.startTimeOffset = CMTime(value: 1, timescale: 1)
// Setup Input of Audio.
let audioCompressionSettings: [String: Any] = [
AVFormatIDKey: kAudioFormatMPEG4AAC,
AVSampleRateKey: 44_100,
AVNumberOfChannelsKey: 1,
AVEncoderBitRateKey: 128_000
]
audioWriterInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioCompressionSettings)
audioWriterInput!.expectsMediaDataInRealTime = true
assetWriter.add(audioWriterInput!)
// Setup Input of Video.
let videoCompressionSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.h264
]
let videoCompressionSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: 1280,
AVVideoHeightKey: 720,
AVVideoCompressionPropertiesKey: [
kVTCompressionPropertyKey_AverageBitRate: 1_024_000,
kVTCompressionPropertyKey_ProfileLevel: kVTProfileLevel_H264_Baseline_AutoLevel
]
]
videoWriterInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoCompressionSettings)
videoWriterInput!.expectsMediaDataInRealTime = true
pixelBuffer = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: videoWriterInput!, sourcePixelBufferAttributes: [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)])
assetWriter.add(videoWriterInput!)
// Configure the asset writer for writing data in fragmented MPEG-4 format.
assetWriter.outputFileTypeProfile = AVFileTypeProfile.mpeg4AppleHLS
assetWriter.preferredOutputSegmentInterval = CMTime(seconds: 1.0, preferredTimescale: 1)
assetWriter.initialSegmentStartTime = startTimeOffset
assetWriter.delegate = self
// start AssetWriiter
startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: startTime)
}
let isVideo = output is AVCaptureVideoDataOutput
if isVideo {
if videoWriterInput.isReadyForMoreMediaData {
videoWriterInput!.append(sampleBuffer)
}
}else{
if audioWriterInput!.isReadyForMoreMediaData {
audioWriterInput!.append(sampleBuffer)
}
}
}
func assetWriter(_ writer: AVAssetWriter, didOutputSegmentData segmentData: Data, segmentType: AVAssetSegmentType, segmentReport: AVAssetSegmentReport?) {
:
:
}
We have to play some encrypted videos from server.
In AVAssetResourceLoaderDelegate we got the ckc data correctly and responded with that. Then video just starts playing and stops immdediately. When we check the playerItem error description we got Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo={NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.}. Any one encountered this?
I am trying to set up HLS with MV HEVC. I have an MV HEVC MP4 converted with AVAssetWriter that plays as a "spatial video" in Photos in the simulator. I've used ffmpeg to fragment the video for HLS (sample m3u8 file below).
The HLS of the mp4 plays on a VideoMaterial with an AVPlayer in the simulator, but it is hard to determine if the streamed video is stereo. Is there any guidance on confirming that the streamed mp4 video is properly being read as stereo?
Additionally, I see that REQ-VIDEO-LAYOUT is required for multivariant HLS. However if there is ONLY stereo video in the playlist is it needed? Are there any other configurations need to make the device read as stereo?
Sample m3u8 playlist
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:12.512500,
sample_video0.ts
#EXTINF:8.341667,
sample_video1.ts
#EXTINF:12.512500,
sample_video2.ts
#EXTINF:8.341667,
sample_video3.ts
#EXTINF:8.341667,
sample_video4.ts
#EXTINF:12.433222,
sample_video5.ts
#EXT-X-ENDLIST
Can we confirm that as of iOS 16.3.1, key frames for MPEGTS via HLS are mandatory now?
I've been trying to figure out why https://chaney-field3.click2stream.com/ shows "Playback Error" across Safari, Chrome, Firefox, etc.. I ran the diagnostics against one of the m3u8 files that is generated via Developer Tools (e.g. mediastreamvalidator "https://e1-na7.angelcam.com/cameras/102610/streams/hls/playlist.m3u8?token=" and then hlsreport validation_data.json) and see this particular error:
Video segments MUST start with an IDR frame
Variant #1, IDR missing on 3 of 3
Does Safari and iOS devices explicitly block playback when it doesn't find one? From what I understand AngelCam simply acts as a passthrough for the video/audio packets and does no transcoding but converts the RTSP packets into HLS for web browsers But IP cameras are constantly streaming their data and a user connecting to the site may be receiving the video between key frames, so it would likely violate this expectation.
From my investigation it also seems like this problem also started happening in iOS 16.3? I'm seeing similar reports for other IP cameras here:
https://ipcamtalk.com/threads/blue-iris-ui3.23528/page-194#post-754082
https://www.reddit.com/r/BlueIris/comments/1255d78/ios_164_breaks_ui3_video_decode/
For what it's worth, when I re-encoded the MPEG ts files (e.g. ffmpeg-i /tmp/streaming-master-m4-na3.bad/segment-375.ts -c:v h264 /tmp/segment-375.ts) it strips the non key frames in the beginning and then playback works properly if I host the same images on a static site and have the iOS device connect to it.
It seems like Chrome, Firefox, VLC, and ffmpeg are much more forgiving on missing key frames. I'm wondering what the reason for enforcing this requirement? And can I confirm it's been a recent change?