Hi y'all,
After getting mono recording working, I want to differentiate my app from the standard voice memos to allow for stereo recording. I followed this tutorial (https://developer.apple.com/documentation/avfaudio/capturing_stereo_audio_from_built-in_microphones) to get my voice recorder to record stereo audio. However, when I look at the waveform in Audacity, both channels are the same. If I look at the file info after sharing it, it says the file is in stereo. I don't exactly know what's going on here. What I suspect is happening is that the recorder is only using one microphone. Here is the relevant part of my recorder:
// MARK: - Initialization
override init() {
super.init()
do {
try configureAudioSession()
try enableBuiltInMicrophone()
try setupAudioRecorder()
} catch {
// If any errors occur during initialization,
// terminate the app with a fatalError.
fatalError("Error: \(error)")
}
}
// MARK: - Audio Session and Recorder Configuration
private func enableBuiltInMicrophone() throws {
let audioSession = AVAudioSession.sharedInstance()
let availableInputs = audioSession.availableInputs
guard let builtInMicInput = availableInputs?.first(where: { $0.portType == .builtInMic }) else {
throw Errors.NoBuiltInMic
}
do {
try audioSession.setPreferredInput(builtInMicInput)
} catch {
throw Errors.UnableToSetBuiltInMicrophone
}
}
private func configureAudioSession() throws {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.record, mode: .default, options: [.allowBluetooth])
try audioSession.setActive(true)
} catch {
throw Errors.FailedToInitSessionError
}
}
private func setupAudioRecorder() throws {
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd, HH:mm:ss"
let timestamp = dateFormatter.string(from: date)
self.recording = Recording(name: timestamp)
guard let fileURL = recording?.returnURL() else {
fatalError("Failed to create file URL")
}
self.currentURL = fileURL
print("Recording URL: \(fileURL)")
do {
let audioSettings: [String: Any] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVLinearPCMIsNonInterleaved: false,
AVSampleRateKey: 44_100.0,
AVNumberOfChannelsKey: isStereoSupported ? 2 : 1,
AVLinearPCMBitDepthKey: 16,
AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue
]
audioRecorder = try AVAudioRecorder(url: fileURL, settings: audioSettings)
} catch {
throw Errors.UnableToCreateAudioRecorder
}
audioRecorder.delegate = self
audioRecorder.prepareToRecord()
}
//MARK: update orientation
public func updateOrientation(withDataSourceOrientation orientation: AVAudioSession.Orientation = .front, interfaceOrientation: UIInterfaceOrientation) async throws {
let session = AVAudioSession.sharedInstance()
guard let preferredInput = session.preferredInput,
let dataSources = preferredInput.dataSources,
let newDataSource = dataSources.first(where: { $0.orientation == orientation }),
let supportedPolarPatterns = newDataSource.supportedPolarPatterns else {
return
}
isStereoSupported = supportedPolarPatterns.contains(.stereo)
if isStereoSupported {
try newDataSource.setPreferredPolarPattern(.stereo)
}
try preferredInput.setPreferredDataSource(newDataSource)
try session.setPreferredInputOrientation(interfaceOrientation.inputOrientation)
}
Here is the relevant part of my SwiftUI view:
RecordView()
.onAppear {
Task {
if await AVAudioApplication.requestRecordPermission() {
// The user grants access. Present recording interface.
print("Permission granted")
} else {
// The user denies access. Present a message that indicates
// that they can change their permission settings in the
// Privacy & Security section of the Settings app.
model.showAlert.toggle()
}
try await recorder.updateOrientation(interfaceOrientation: deviceOrientation)
}
}
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let orientation = windowScene.windows.first?.windowScene?.interfaceOrientation {
deviceOrientation = orientation
Task {
do {
try await recorder.updateOrientation(interfaceOrientation: deviceOrientation)
} catch {
throw Errors.UnableToUpdateOrientation
}
}
}
}
Here is the full repo: https://github.com/aabagdi/MemoMan/tree/MemoManStereo
Thanks for any leads!
AVFoundation
RSS for tagWork with audiovisual assets, control device cameras, process audio, and configure system audio interactions using AVFoundation.
Posts under AVFoundation tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello,
We are currently developing a device with a USB-C drive, and we want to connect it to iOS devices to import the stored files into our app.
I have a few questions regarding this:
MFi Certification Requirement
We believe that MFi certification is not necessary for USB-C connections. Is this understanding correct?
Implementation Method
We prefer not to use standard components like UIDocumentPickerViewController. Are there any methods to access the file system directly, or any other suitable approaches you can recommend?
If anyone has experience with this, your advice would be greatly appreciated. Thank you in advance.
I am trying to export an AVMutableComposition with a single audio track. This track has a scaled AVCompositionTrackSegment to simulate speed changes up to 20x. I need to use AVAssetWriter and AVAssetReader classes for this task. When I scale the source duration up to a maximum of 5x, everything works fine. However, when I scale it to higher speeds, such as 20x, the app hangs on the copyNextSampleBuffer method. I'm not sure why this is happening and how to prevent it. Also, this often happens if the exported audio track has segments with different speeds. (The duration of the audio file in the example is 47 seconds.)
Example of code:
class Export {
func startExport() {
let inputURL = Bundle.main.url(forResource: "Piano", withExtension: ".m4a")!
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let outputURL = documentsDirectory.appendingPathComponent("Piano20x.m4a")
try? FileManager.default.removeItem(at: outputURL)
print("Output URL: \(outputURL)")
changeAudioSpeed(inputURL: inputURL, outputURL: outputURL, speed: 20)
}
func changeAudioSpeed(inputURL: URL, outputURL: URL, speed: Float) {
let urlAsset = AVAsset(url: inputURL)
guard let assetTrack = urlAsset.tracks(withMediaType: .audio).first else { return }
let composition = AVMutableComposition()
let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
try compositionAudioTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: assetTrack.timeRange.duration), of: assetTrack, at: .zero)
} catch {
print("Failed to insert audio track: \(error)")
return
}
let scaledDuration = CMTimeMultiplyByFloat64(assetTrack.timeRange.duration, multiplier: Double(1.0 / speed))
compositionAudioTrack?.scaleTimeRange(CMTimeRangeMake(start: .zero, duration: assetTrack.timeRange.duration), toDuration: scaledDuration)
print("Scaled audio from \(assetTrack.timeRange.duration.seconds)sec to \(scaledDuration.seconds) sec")
compositionAudioTrack?.segments
do {
let compositionAudioTracks = composition.tracks(withMediaType: .audio)
let assetReader = try AVAssetReader(asset: composition)
let audioSettings: [String: Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVLinearPCMBitDepthKey: 16,
AVLinearPCMIsBigEndianKey: false,
AVLinearPCMIsFloatKey: false,
AVLinearPCMIsNonInterleaved: false
]
let readerOutput = AVAssetReaderAudioMixOutput(audioTracks: compositionAudioTracks,
audioSettings: audioSettings)
assetReader.add(readerOutput)
let assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: .m4a)
let writerInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioSettings)
assetWriter.add(writerInput)
assetReader.startReading()
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: .zero)
let conversionQueue = DispatchQueue(label: "ConversionQueue")
writerInput.requestMediaDataWhenReady(on: conversionQueue) {
while writerInput.isReadyForMoreMediaData {
if let sampleBuffer = readerOutput.copyNextSampleBuffer() { // APP hangs here!!!
writerInput.append(sampleBuffer)
} else {
writerInput.markAsFinished()
assetWriter.finishWriting {
print("Export completed successfully")
}
break
}
}
}
} catch {
print("Failed with error: \(error)")
}
}
}
Hi all,
I tried the "isSpatialVideoCaptureEnabled" with AVCaptureMovieFileOutput mentioned in WWDC24: Build compelling spatial photo and video experiences, and it works.
But there are some issues and questions:
Below codes, the change.newValue always nil so the code seems not work.
let observation = videoDevice.observe(\.spatialCaptureDiscomfortReasons) { (device, change) in
guard let newValue = change.newValue else { return }
if newValue.contains(.subjectTooClose) {
// Guide user to move back
}
if newValue.contains(.notEnoughLight) {
// Guide user to find a brighter environment
}
}
AVCaptureMovieFileOutput is support spatial video capturing.
May I ask if AVCaptureVideoDataOutput will also support spatial video capturing?
I have an mp4 file (which is around 25min) which i need to play but if i open it in quick time player or AVplayer, it shows as around 55min in those two platfroms. I don't understand why this happens. It correctly shows the time when opening with a browser or VSCode built in video playback.
Here is the link to the file:
https://www.dropbox.com/scl/fi/hbg59uqx8xdpiqbnx5wz8/videoplayback-1.mp4?rlkey=7o8l8m7j8dhq0o6f3zssgv9bd&st=5lt6apug&dl=0
My app has encountered many watchdog issues on iOS 17, with stack traces as follows:
Attributed: Call stack 0:
mach_msg2_trap (in libsystem_kernel.dylib) + 7
mach_msg2_internal (in libsystem_kernel.dylib) + 79
mach_msg_overwrite (in libsystem_kernel.dylib) + 435
mach_msg (in libsystem_kernel.dylib) + 23
_dispatch_mach_send_and_wait_for_reply (in libdispatch.dylib) + 543
dispatch_mach_send_with_result_and_wait_for_reply (in libdispatch.dylib) + 59
xpc_connection_send_message_with_reply_sync (in libxpc.dylib) + 263
FigXPCConnectionSendSyncMessageCreatingReply (in CoreMedia) + 291
FigXPCRemoteClientSendSyncMessageCreatingReply (in CoreMedia) + 47
FigCaptureSessionRemoteCreate (in CMCapture) + 131
-[AVCaptureSession _createFigCaptureSession] (in AVFCapture) + 123
-[AVCaptureSession _initWithMediaEnvironment:] (in AVFCapture) + 619
-[AVCaptureSession init] (in AVFCapture) + 415
We also have many iOS 16 users, but have never encountered a watchdog issue with the AVCaptureSession init method in iOS 16. Is there any change in iOS 17 that could have caused this? How can I avoid this issue?
The complete stack trace is attached
avfoundation-watchdog.txt
I'm working on streaming tvOS app and as you know there are mostly two type of video streams - live and vod. AVPlayerViewController handles these types of streams by showing respective playback controls.
Recently I got a task to implement synchronous vod playback(syncVod), it's when we need to simulate live playback while actual vod stream playback.
In order to simulate live playback below things needs to be handled:
Disabling scrubbing via remote. (Done. playerVc.requiresLinearPlayback = true)
Disabling info panel view w/play "From beginning" button. (Done, playerVc.playbackControlsIncludeInfoViews = false)
Disabling play/pause button.(Done, not ideally though. On rate change observer - if player.rate == 0 && playbackMode == .syncVod { player.play() return }). Why not ideal solution - tapping on remote causes quite short hiccup in playback - but playback resumes, no actual pause happens.
Hiding progress bar and time labels. :(
Point #4 is the main problem, we can't hide progress bar and it's related UI elements(time labels) particularly, but only hide all playback controls - playerVc.showsPlaybackControls = false. The thing is I have custom buttons in transportBarCustomMenuItems and hiding all playback controls is not the right option for me.
Implementing custom playback controls panel is kind of heavy lift, but as of now it seems the only proper way of implementing syncVod playback ideally.
Did anyone face similar issue and could resolve it w/out implementing custom playback controls panel ? Is there way to hide progress bar only in tvOS AVPlayerViewController?
While using the native AVfoundation for recording videos I am able to see black frames/ screen in the beginning and end of the video for 2 millisecond at the end and beginning .
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
guard isRecording, let assetWriter = assetWriter else { return }
let timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
if recordingStartTime == nil {
recordingStartTime = timestamp
let adjustedStartTime = CMTimeAdd(timestamp, CMTimeMake(value: -2, timescale: 1000)) // Adjust start time slightly earlier
assetWriter.startSession(atSourceTime: adjustedStartTime)
print("Status: \(assetWriter.status.rawValue)")
}
if output == videoOutput {
if videoInput?.isReadyForMoreMediaData == true {
videoInput?.append(sampleBuffer)
}
} else if output == audioOutput {
if audioInput?.isReadyForMoreMediaData == true {
audioInput?.append(sampleBuffer)
}
}
if let startTime = recordingStartTime, CMTimeSubtract(timestamp, startTime) >= recordingInterval {
isRecording = false
let adjustedEndTime = CMTimeAdd(timestamp, CMTimeMake(value: 2, timescale: 1000)) // Adjust end time slightly later
assetWriter.finishWriting { [weak self] in
print("Finished writing segment")
self?.startRecording() // Start a new recording segment
}
recordingStartTime = nil
}
}
Hello, today when we uploaded a new TestFlight Mac Catalyst build we received an email about the build being invalid:
TMS-90338: Non-public API usage - The app references non-public symbols in {app name}: _AVCaptureDeviceTypeBuiltInTelephotoCamera, _AVCaptureDeviceTypeBuiltInTrueDepthCamera, _AVCaptureDeviceTypeBuiltInUltraWideCamera, _AVCaptureSessionInterruptionReasonKey, _AVCaptureSessionInterruptionSystemPressureStateKey, _AVCaptureSystemPressureLevelCritical, _AVCaptureSystemPressureLevelFair, _AVCaptureSystemPressureLevelNominal, _AVCaptureSystemPressureLevelSerious, _AVCaptureSystemPressureLevelShutdown. If method names in your source code match the private Apple APIs listed above, altering your method names will help prevent this app from being flagged in future submissions. In addition, note that one or more of the above APIs may be located in a static library that was included with your app. If so, they must be removed. For further information, visit the Technical Support Information at http://developer.apple.com/support/technical/
We've been uploading builds the same way for months, using the same Xcode 15.2 and dependency versions, and have checked our most recent commits since the last release and nothing was updated around AVFoundation, archiving, etc. Did anything change on Apple's side recently?
We use Xcode 15.2 to build/archive/upload and xcodebuild to run all commands.
I have an app that uses a MultiCamCaptureSession, the devices of which are builtInUltraWideCamera and builtInLiDARDepthCamera cameras. Occasionally when outside I get some frame drops due to discontinuity that end in the media services being reset:
[06-24 11:27:13][CameraSession] Capture session runtime error: related decl 'e' for AVError(_nsError: Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" UserInfo={NSLocalizedDescription=Cannot Complete Action, NSLocalizedRecoverySuggestion=Try again later.})
This runtime error notification is always superseded by 4-5 frame drops :
[06-24 11:27:10][CaptureSession] Dropped frame because Discontinuity
Logging the system temperature shows
[06-24 11:27:10][CaptureSession] Temperature is 'Fair'
I have some inclination that the frame discontinuity is being caused by the whileBalanceMode of the capture session, perhaps the algorithm requires 5 recent frames to work. I had a similar problem with the lidar depth camera where with filtering enabled exactly 5 frame drops would make the media services reset.
When the whiteBalanceMode is locked I do slightly better with 10 frame drops before the mediaServices are reset.
Is there any logging utility to determine the actual reason? All of these sampleBuffers come with no info attachment only the not so useful "Dropped frame because Discontinuity." Any ideas for solving this would be helpful as well. Maybe tuning the camera to work better with quickly varying lighting conditions?
A small number of crashes are being reported on Firebase. When attempting to use the insertTimeRange:ofAsset:atTime:error: method of AVMutableComposition, a crash occurred with the error message -[__NSArrayM insertObject:atIndex:]: object cannot be nil.
Most of them appear in versions of ios 17.0 and above.
Here's my code:
- (AVMutableComposition *)createtrimAsset:(AVAsset *)asset
andStartTime:(CGFloat)startTime
endTime:(CGFloat)endTime{
NSError *error = nil;
CGFloat timescale = 1000000;
AVMutableComposition *mutableComposition = [AVMutableComposition composition];
CMTime sStartTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)*startTime, timescale);
CMTime eEndTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(asset.duration)*endTime, timescale);
[mutableComposition insertTimeRange:CMTimeRangeMake(sStartTime, CMTimeSubtract(eEndTime, sStartTime)) ofAsset:asset atTime:kCMTimeZero error:&error];
return mutableComposition;
}
I attempted to reproduce this crash by deliberately setting the timeRange or asset to unusual values, such as asset=nil, or asset.duration=0, or asset.duration=NAN, but all attempts failed.
What could be causing this exception? Any advice would be of great help to me.
Hello everyone, with the release of Apple's new Final Cut Camera App, we see the possibility to overlay a Focus Peaking indicator over the camera feed, showing focussed areas.
We have already had a contrast based autofocus system for some time via the AVCaptureDevice.Format.AutoFocusSystem.contrastDetection, but I haven't found a way to actually present contrast areas to the user.
Given that Apple now natively has such an algorithm for the Final Cut Camera App, I wonder if we devs now also get access to this. If not, does anybody know of implementations of focus peaking out there?
Thanks and with best regards
iOS17.4 17.5.1
AVPlayer
https://svip.yzzy23-play.com/20240606/14121_017bbbeb/index.m3u8
大概在8:30s时会无声 我测试过系统safari也会出现这样的情况
之前版本都没问题
I’m creating a objective C command-line utility to encode RAW image sequences to ProRes 4444, but I’m encountering, blocky compression artifacts in the ProRes 4444 video output.
To test the integrity of the image data before encoding to ProRes, I added a snippet in my encoding function that saves a 16-bit PNG before encoding to ProRes and the PNG looks perfect, I can see all detail in every part of the image dynamic range.
Here’s a comparison between the 16-bit PNG(on the right) and the ProRes 4444 output. (on the left)
As a further test, I re-encoded the ‘test PNG’ to ProRes 4444 using DaVinci Resolve, and the ProRes4444 output video from Resolve doesn’t have any blocky compression artifacts. Looks identical.
In short, this is what the utility does:
Unpacks the 12-bit raw data into 16-bit values. After unpacking, the raw data is debayered to convert it into a standard color image format (BGR) using OpenCV.
Scale the debayered pixel values from their original 12-bit depth to fit into a 16-bit range. Up to this point everything is fine and confirmed by saving 16bit PNGs.
The images are encoded to ProRes 4444 using the AVFoundation framework.
The pixel buffers are created and managed using dictionary method with ‘kCVPixelFormatType_64RGBALE’.
I need help figuring this out, I’m a real novice when it comes to AVfoundation/encoding to ProRes.
See relevant parts of my 'encodeToProRes' function:
void encodeToProRes(const std::string &outputPath, const std::vector<std::string> &rawPaths, const std::string &proResFlavor) {
NSError *error = nil;
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:outputPath.c_str()]];
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:url fileType:AVFileTypeQuickTimeMovie error:&error];
if (error) {
std::cerr << "Error creating AVAssetWriter: " << error.localizedDescription.UTF8String << std::endl;
return;
}
// Load the first image to get the dimensions
std::cout << "Debayering the first image to get dimensions..." << std::endl;
Mat firstImage;
int width = 5320;
int height = 3900;
if (!debayer_image(rawPaths[0], firstImage, width, height)) {
std::cerr << "Error debayering the first image" << std::endl;
return;
}
width = firstImage.cols;
height = firstImage.rows;
// Save the first frame as a PNG 16-bit image for validation
std::string pngFilePath = outputPath + "_frame1.png";
if (!imwrite(pngFilePath, firstImage)) {
std::cerr << "Error: Failed to save the first frame as a PNG image" << std::endl;
} else {
std::cout << "First frame saved as PNG: " << pngFilePath << std::endl;
}
NSString *codecKey = nil;
if (proResFlavor == "4444") {
codecKey = AVVideoCodecTypeAppleProRes4444;
} else if (proResFlavor == "422HQ") {
codecKey = AVVideoCodecTypeAppleProRes422HQ;
} else if (proResFlavor == "422") {
codecKey = AVVideoCodecTypeAppleProRes422;
} else if (proResFlavor == "LT") {
codecKey = AVVideoCodecTypeAppleProRes422LT;
} else {
std::cerr << "Error: Invalid ProRes flavor specified: " << proResFlavor << std::endl;
return;
}
NSDictionary *outputSettings = @{
AVVideoCodecKey: codecKey,
AVVideoWidthKey: @(width),
AVVideoHeightKey: @(height)
};
AVAssetWriterInput *videoInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings];
videoInput.expectsMediaDataInRealTime = YES;
NSDictionary *pixelBufferAttributes = @{
(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_64RGBALE),
(id)kCVPixelBufferWidthKey: @(width),
(id)kCVPixelBufferHeightKey: @(height)
};
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoInput sourcePixelBufferAttributes:pixelBufferAttributes];
...
[assetWriter startSessionAtSourceTime:kCMTimeZero];
CMTime frameDuration = CMTimeMake(1, 24); // Frame rate of 24 fps
int numFrames = static_cast<int>(rawPaths.size());
...
// Encoding thread
std::thread encoderThread([&]() {
int frameIndex = 0;
std::vector<CVPixelBufferRef> pixelBufferBuffer;
while (frameIndex < numFrames) {
std::unique_lock<std::mutex> lock(queueMutex);
queueCondVar.wait(lock, [&]() { return !frameQueue.empty() || debayeringFinished; });
if (!frameQueue.empty()) {
auto [index, debayeredImage] = frameQueue.front();
frameQueue.pop();
lock.unlock();
if (index == frameIndex) {
cv::Mat rgbaImage;
cv::cvtColor(debayeredImage, rgbaImage, cv::COLOR_BGR2RGBA);
CVPixelBufferRef pixelBuffer = NULL;
CVReturn result = CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &pixelBuffer);
if (result != kCVReturnSuccess) {
std::cerr << "Error: Could not create pixel buffer" << std::endl;
dispatch_group_leave(dispatchGroup);
return;
}
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pixelBuffer);
for (int row = 0; row < height; ++row) {
memcpy(static_cast<uint8_t*>(pxdata) + row * CVPixelBufferGetBytesPerRow(pixelBuffer),
rgbaImage.ptr(row),
width * 8);
}
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
pixelBufferBuffer.push_back(pixelBuffer);
...
Thanks very much!
I'm working on a macOS application that captures audio and video. When the user selects a video capture source (most likely an elgato box), I would like the application to automatically select the audio input from the same device. I was achieving this by pairing video and audio sources that had the same name, but this doesn't work when the user plugs in two capture devices of the same make and model.
With the command system_profiler SPUSBDataType I can list all the USB devices, and I can see that the two elgato boxes have different serial numbers. If I could find this serial number, then I could figure out which AVCaptureDevices come from the same hardware.
Is there a way to get the manufacturer's serial number from the AVCaptureDevice object? Or a way to identify the USB device for an AVCaptureDevice, and from there I could get the serial or some other unique ID?
I am trying to record many AVplayers playing in a UIView.
But when I record that UIView I can't see AVPlayers which are playing...!
what's the matter?????
Playing fMP4 HLS stream on VisionOS beta. This is the stream, HEVC main 10 and EAC3 6 channel:
#EXT-X-STREAM-INF:BANDWIDTH=6760793,AVERAGE-BANDWIDTH=6760793,VIDEO-RANGE=PQ,CODECS="hvc1.2.4.L150.B0,mp4a.a6",RESOLUTION=3840x2160,FRAME-RATE=23.976,SUBTITLES="subs"
This is what AVPlayer says:
Error Domain=AVFoundationErrorDomain Code=-11848 "Cannot Open" UserInfo={NSLocalizedFailureReason=The media cannot be used on this device., NSLocalizedDescription=Cannot Open, NSUnderlyingError=0x3009e37b0 {Error Domain=CoreMediaErrorDomain Code=-15517 "(null)"}}
I can't find any documentation for the underlying error 15517.
Is it because "mp4a.a6" is declared in the codec list and not "ec-3"?
hlsreport has these MUST FIX issues:
1. Measured peak bitrate compared to multivariant playlist declared value exceeds error tolerance
Multivariant Playlist Stream Definition for All Variants
2. Stereo audio in AAC-LC, HE-AAC v1, or HE-AAC v2 format MUST be provided
Multivariant Playlist
3. If Dolby Digital Plus is provided then Dolby Digital MUST be provided also
Multivariant Playlist
4. I-frame playlists ( EXT-X-I-FRAME-STREAM-INF ) MUST be provided to support scrubbing and scanning UI
Multivariant Playlist
5. The server MUST deliver playlists using gzip content-encoding
All Variants
All Renditions
Multivariant Playlist
6. You MUST provide multiple bit rates of video
Multivariant Playlist
7. Playlist codec type doesn't match content codec type
All Variants
8. (Segment) The operation couldn’t be completed. (HTTPPumpErrorDomain error -16845 - HTTP 400: (unhandled))
(list of subtitle renditions)
9. (Segment) HTTP 400 - HTTP/2.0 400 Bad Request
(list of subtitle renditions)
10. Multichannel audio MUST be separate audio stream
All Variants
11. If EXT-X-INDEPENDENT-SEGMENTS is not in the multivariant playlist, then you MUST use the EXT-X-INDEPENDENT-SEGMENTS tag in all video media playlists
All Variants
12. The CODECS attribute MUST include every media format present
All Variants, does not declare EC-3
We are developing a custom keyboard with barcode scanning functionality in Swift.
Since the camera function cannot be used to scan on the custom keyboard, we are considering using the hosting app to perform the scanning and then return to the host app.
Is there any way to automatically return to the host app after scanning in the hosting app?
In the following apps that I have benchmarked,
Custom Keyboard > Scan in Hosting App > Automatically return to host app after scan
This transition seems to be achievable.
https://apps.apple.com/jp/app/imagerswift/id1469166411
We have investigated and verified the following three points
whether it is possible to come back to the keyboard app with a custom URL scheme
→The keyboard app does not allow custom URLs to be set.
Can we return to the host app with a custom URL scheme?
→The keyboard app cannot recognize which app is the host app.
Is it possible to press the Back to xxxx link that appears in the upper left corner of the screen as an iOS function?
→Cannot be controlled from the app.
I just follow the video and add the codes, but when I switch to spatial video capturing, the videoPreviewLayer shows black.
<<<< FigCaptureSessionRemote >>>> Fig assert: "! storage->connectionDied" at bail (FigCaptureSessionRemote.m:405) - (err=0)
<<<< FigCaptureSessionRemote >>>> captureSessionRemote_getObjectID signalled err=-16405 (kFigCaptureSessionError_ServerConnectionDied) (Server connection was lost) at FigCaptureSessionRemote.m:405
<<<< FigCaptureSessionRemote >>>> Fig assert: "err == 0 " at bail (FigCaptureSessionRemote.m:421) - (err=-16405)
<<<< FigCaptureSessionRemote >>>> Fig assert: "msg" at bail (FigCaptureSessionRemote.m:744) - (err=0)
Did I miss something?
Hello,
We've a music app reading MPMediaItem.
We got items using MPMediaQuery. But we realized that some downloaded tracks from Apple Music were fetched too. Not all downloaded track but only those who were played recently.
Of course, since these tracks are protected with DRM we can't play them in our player.
It's weird to get them in our query because we added predicate in order to dont fetch protected asset and iCloud item
MPMediaPropertyPredicate(value: false, forProperty: MPMediaItemPropertyHasProtectedAsset)
MPMediaPropertyPredicate(value: false, forProperty: MPMediaItemPropertyIsCloudItem)
To be sure, we made a second check on each item we've fetched
extension MPMediaItem {
public func isValid() -> Bool {
return self.assetURL != nil && !self.isCloudItem && !self.hasProtectedAsset
}
}
But we still get these items. Their hasProtectedAsset attribute always return false.
I dont know if it's a bug, but since we can't detect this items as Apple Music downloaded track, we can't either:
filter them to not add them in our application library
OR
switch on a MPMusicPlayerController.applicationMusicPlayer to allow the user to play them