I am working on a project where I'm using FastAPI to handle WebSocket connections for receiving video blobs from a Media Recorder. The goal is to create video parts with a size limit of 5 MB and save them as separate files. The initial part works well, but subsequent parts seem to be corrupted, and I'm facing playback issues.
I've tried to handle buffering and file writing within the loop, and I suspect that the way I'm managing file operations might be causing the corruption. Can someone review my code and provide insights into why subsequent video parts are not playable?
Here is a snippet of the relevant code:
//frontend
recorder.ondataavailable = (e: BlobEvent) => {
socket.send(e.data)
}
recorder.start(1000)
@app.websocket("/video")
async def websocket_endpoint(websocket: WebSocket, token: str = Query(...), videoId: str = Query(...), authorize: AuthJWT = Depends()):
await manager.connect(websocket)
temp_dir = os.path.join("temp", videoId)
os.makedirs(temp_dir, exist_ok=True)
queueNumber = 1
bufferedSize = 0
totalRequiredBufferSize = 5 * 1024 * 1024
print(f"{datetime.utcnow()}: Client connected: {websocket.client.host}")
try:
while True:
try:
data = await websocket.receive_bytes()
file = open(os.path.join(temp_dir, f"{videoId}-video-{queueNumber}.webm"), 'ab')
if bufferedSize < totalRequiredBufferSize:
if data:
file.write(data)
bufferedSize = bufferedSize + len(data)
print(f"buffered size = {bufferedSize} and blob size = ${len(data) / (1024 * 1024)}")
elif bufferedSize >= totalRequiredBufferSize:
if data:
file.write(data)
print(f"End= {queueNumber} and blob size = ${bufferedSize / (1024 * 1024)}")
file.close()
bufferedSize = 0
queueNumber = queueNumber + 1
except WebSocketDisconnect:
print(f"Client disconnected: {websocket.client.host}")
manager.disconnect(websocket)
This is how the files are looking :-
I appreciate any suggestions or guidance on how to correctly handle file operations within a FastAPI WebSocket loop, especially when dealing with Media Recorder blobs.
Thank you!
Nothing is corrupted, it's just that you can't arbitrarily cut a file and expect it to work. You've cut off all the initialization information.
Additionally, you can't cut on MediaRecorder data event data either. It's meant to be a continuous stream, and the data event just gives you some convenient sized chunks.... they are not necessarily segments (even though in practice, they basically are).
Each container format has its own way to deal with this. For WebM, see my previous answer here: https://stackoverflow.com/a/62237720/362536