{"id":19492810,"url":"https://github.com/oatpp/example-yuv-websocket-stream","last_synced_at":"2025-04-25T20:30:41.879Z","repository":{"id":98397862,"uuid":"266327360","full_name":"oatpp/example-yuv-websocket-stream","owner":"oatpp","description":"Oat++ example on how to stream raw YUV images from V4L2 via websockets to an HTML5 canvas","archived":false,"fork":false,"pushed_at":"2024-04-22T21:30:45.000Z","size":34,"stargazers_count":13,"open_issues_count":2,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-29T22:51:44.978Z","etag":null,"topics":["oatpp","v4l2","websocket"],"latest_commit_sha":null,"homepage":"https://oatpp.io/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oatpp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-23T12:00:14.000Z","updated_at":"2024-10-14T06:59:18.000Z","dependencies_parsed_at":"2024-11-07T00:24:43.180Z","dependency_job_id":"16d8d17b-2b18-4e3e-906d-70b23e7756f6","html_url":"https://github.com/oatpp/example-yuv-websocket-stream","commit_stats":{"total_commits":10,"total_committers":3,"mean_commits":"3.3333333333333335","dds":"0.19999999999999996","last_synced_commit":"5c77d2eb5387096bbbd37035dcb9818d762c9206"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oatpp%2Fexample-yuv-websocket-stream","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oatpp%2Fexample-yuv-websocket-stream/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oatpp%2Fexample-yuv-websocket-stream/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oatpp%2Fexample-yuv-websocket-stream/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oatpp","download_url":"https://codeload.github.com/oatpp/example-yuv-websocket-stream/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224015660,"owners_count":17241535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["oatpp","v4l2","websocket"],"created_at":"2024-11-10T21:23:08.155Z","updated_at":"2024-11-10T21:23:08.623Z","avatar_url":"https://github.com/oatpp.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Example-YUV-Websocket-Stream [![Build Status](https://dev.azure.com/lganzzzo/lganzzzo/_apis/build/status/oatpp.example-yuv-websocket-stream?branchName=master)](https://dev.azure.com/lganzzzo/lganzzzo/_build/latest?definitionId=25\u0026branchName=master)\n\nExample project how-to create a YUV image stream from a V4L device (i.E. Webcam) using websockets.\nThe raw YUV image stream is send via a websocket connection. In the example Webpage, this YUV stream is converted to an HTML5 Canvas using JavaScript. \nIf you experience lag in the video its either your PC not being fast enough for the JavaScript conversion or the V4L2 stack.\nThe example webpage also runs fine on newer Smartphones!\n\nSee more:\n\n- [Oat++ Website](https://oatpp.io/)\n- [Oat++ Github Repository](https://github.com/oatpp/oatpp)\n- [Get Started](https://oatpp.io/docs/start)\n\n## Overview\n\nThis project is using [oatpp](https://github.com/oatpp/oatpp), [oatpp-websocket](https://github.com/oatpp/oatpp-websocket) and [oatpp-swagger](https://github.com/oatpp/oatpp-swagger) modules.\n\n### Project layout\n\n```\n|- CMakeLists.txt                        // projects CMakeLists.txt\n|- src/\n|   |\n|   |- controller/                       // Folder containing CamAPIController where all endpoints are declared\n|   |- backend/                          // Folder with \"business logic\"\n|   |- dto/                              // DTOs are declared here\n|   |- SwaggerComponent.hpp              // Swagger-UI config\n|   |- AppComponent.hpp                  // Service config\n|   |- App.cpp                           // main() is here\n|\n|- utility/install-oatpp-modules.sh      // utility script to install required oatpp-modules.\n```\n\n---\n\n### Usage\nWhen running this example, a Oat++ REST-API is launched and a demo webpage is accessible under `\u003cyourip/localhost\u003e:8000/v0/cam/stream`.\nThe raw data is send out on the websocket (`\u003cyourip/localhost\u003e:8000/v0/cam/stream/ws`) as soon as one client is connected and stops if all clients have disconnected.\nEach websocket frame contains a whole image as received from V4L2. \n\n### Quirks\n\n#### Hardcoded Dimensions\n\nThe dimensions are Hardcoded to *640x480* interlaced YUYV. Thus each image _complete_ image is 614400 bytes.\nYou can change the dimensions in `src/backend/V4LGrabber.cpp:589` and have to update them in `res/cam/wsImageView.html:31-32`\n\n**src/backend/V4LGrabber.cpp:589**\n\n```cpp\nfmt.fmt.pix.width       = 640;\nfmt.fmt.pix.height      = 480;\nfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;\nfmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;\n```\n\n**res/cam/wsImageView.html:31-32**\n```js\nconst imgData = ctx.createImageData(640, 480);\nconst grayScale = new Uint8Array(640*480);\n```\n\n#### Partial Images\nSome webcams or V4L2 implementations are buggy and (sometimes) transfer partial images (only).\nWhen you know your image size, you must come up with your own stiching mechanism. \n\n#### Video Lags\nDepending on the used IO method (`read`, `mmap` or `userptr`) between V4L2\u003c-\u003eOat++ some lag can occur or the stream does not work at all.\nThe example is programmed to use `mmap` in `src/controller/CamAPIController.cpp:31`.\n\n```c++\nm_grabber = std::make_shared\u003cV4LGrabber\u003e(device, \u0026CamAPIController::handle_frame, m_imageReceivers.get(), V4LGrabber::IO_METHOD_MMAP);\n```\n\n\nThe methods can roughly be described by:\n\n- **read:** Simple `read` calls on `/dev/videoX` (most simple, widely supported)\n- **mmap:** Memory mapping the data to the user-memory (should be a lot faster, memory efficient)\n- **userptr:** User created memory region is given to kernel and the kernel uses this region as buffer (potentially dangerous, memory efficient)\n\n\n### Build and Run\n\n#### Using CMake\n\n**Requires**\n\n- `oatpp`, `oatpp-websocket` and `oatpp-swagger` modules installed. You may run `utility/install-oatpp-modules.sh` \nscript to install required oatpp modules.\n- Linux with `V4L2` development libraries installed\n\n```\n$ mkdir build \u0026\u0026 cd build\n$ cmake ..\n$ make \n$ ./example-yuv-websocket-stream-exe        # - run application.\n```\n\n#### In Docker\n\n```\n$ docker build -t example-yuv-websocket-stream .\n$ docker run -p 8000:8000 -t example-yuv-websocket-stream-exe\n```\n\n---","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foatpp%2Fexample-yuv-websocket-stream","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foatpp%2Fexample-yuv-websocket-stream","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foatpp%2Fexample-yuv-websocket-stream/lists"}