user28467484
user28467484

Reputation: 11

How can I show data which is coming from Websocket on AVPlayer in Swift

I already have implemented all the functions but when the data comes first time, its playing but when the data comes second time its going in Asset is not playable. I'm not able to confirm why it's happening.

private func receiveMessage() { webSocketTask?.receive { [weak self] result in guard let self = self else { return }
        switch result {
        case .success(let message):
            switch message {
            case .string(let text):
                self.handleIncomingMessage(text)
            case .data(let data):
                self.appendDataToBuffer(data)
            @unknown default:
                print("Unknown message type received")
            }
            
            // Continue receiving messages
            self.receiveMessage()
            
        case .failure(let error):
            print("Failed to receive message: \(error)")
            
            // Check WebSocket state
            if let state = self.webSocketTask?.state {
                print("WebSocket state: \(state)")
                
                // If the connection is still active, try receiving again
                if state == .running {
                    self.receiveMessage()
                } else {
                    print("WebSocket is not running. State: \(state)")
                }
            }
        }
    }
}

This is how I'm appending the data from websocket

func appendDataToBuffer(_ data: Data) {
    self.dataBuffer.append(data)

    bufferQueue.async { [weak self] in
        guard let self = self else { return }
        
        
        if !self.isProcessingBuffer {
            self.startProcessingLoop()
        
        }
    }
}




private func startProcessingLoop() {
    processingQueue.async { [weak self] in
        guard let self = self else { return }
        
        self.isProcessingBuffer = true
        while self.isStreamingActive {
            var chunk: Data?
            
            self.bufferQueue.sync {
                let dynamicChunkSize = self.determineChunkSize()
                               if self.dataBuffer.count >= dynamicChunkSize {
                                   print("Is Databuffer Count is greater than dynamic chunk size \(self.dataBuffer.count >= dynamicChunkSize)")
                                   chunk = self.dataBuffer.prefix(dynamicChunkSize)
                                   self.dataBuffer.removeFirst(dynamicChunkSize)
                               }
            }
            
            guard let chunkToProcess = chunk else {
                usleep(100_000)
                continue
            }
            
            self.processVideoChunk(chunkToProcess)
            
        }
        self.isProcessingBuffer = false
    }
}

private func processVideoChunk(_ chunk: Data) { // Store the chunk in memory videoChunks.append(chunk) {
        // Combine all chunks into a single Data object
        let combinedData = Data(videoChunks.joined())
        
        // Create an AVAsset from the combined data
        guard let tempURL = createTemporaryURL(with: combinedData) else {
            logger.error("Failed to create temporary URL for video data")
            return
        }
        
        DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) { [weak self] in
            guard let self = self else { return }
            
            // Load the AVAsset asynchronously
            let asset = AVAsset(url: tempURL)
            asset.loadValuesAsynchronously(forKeys: ["playable"]) {
                var error: NSError? = nil
                let status = asset.statusOfValue(forKey: "playable", error: &error)
                
                DispatchQueue.main.async {
                    if status == .loaded {
                        self.logger.log("Asset loaded successfully")
                        
                        if asset.isPlayable {
                            self.logger.log("Asset is playable")
                            let playerItem = AVPlayerItem(asset: asset)
                            self.delegate?.pausePlayer()
                            // Use delegate to start the video playback
                                self.delegate?.startVideo(playerItem: playerItem)
                            self.isProcessingBuffer = false
                            // Clean up temporary URL
                            try? FileManager.default.removeItem(at: tempURL)
                            self.clearChunks()
                        } else {
                            self.logger.error("Asset is not playable")
                            try? FileManager.default.removeItem(at: tempURL)
                                                  self.clearChunks()
                                                  self.isProcessingBuffer = false
                        }
                    } else {
                        self.logger.error("Error loading asset: \(error?.localizedDescription ?? "Unknown error")")
                    }
                }
            }
        }
    }
}

Its playing for 2-3 seconds then its falling in Asset is not playable I'm not able to identify what is problem with that.
The data that I'm getting is binary data and I want to show it on my avplayer. Data is of Live Streaming Camera.

Upvotes: 1

Views: 23

Answers (0)

Related Questions