diff --git a/README.md b/README.md index fffc4af..ba91401 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,47 @@ The app will start, displaying a message similar to: Then, connect to `https://72e5-22-159-32-48.ngrok-free.app` to view the result. -## Exxperimental feature: video recording +## Experimental feature: video recording There is a new exxperimental feature to record the stream in [webm](https://en.wikipedia.org/wiki/WebM) format. This is available on the side menu. [See this example with audio](docs/goMarkableStreamRecording.webm) +## Experimental Feature: Embedded Presentations and Videos + +### Overview + +`goMarkableStream` introduces an innovative experimental feature that allows users to set a presentation or video in the background, enabling live annotations using a reMarkable tablet. This feature is ideal for enhancing presentations or educational content by allowing dynamic, real-time interaction. + +### How It Works + +- To use this feature, append `?present=https://url-of-the-embedded-file` to your streaming URL. +- This action will embed your chosen presentation or video in the stream's background. +- You can then annotate or draw on the reMarkable tablet, with your input appearing over the embedded content in the stream. + +### Usage Example + +- **Live Presentation Enhancement**: For instance, using Google Slides, you can leave spaces in your slides or use a blank slide to write additional content live. This feature is perfect for educators, presenters, and anyone looking to make their presentations more interactive and engaging. + +![](docs/gorgoniaExample.png) + +### Compatibility + +- The feature works with any content that can be embedded in an iframe. This includes a variety of presentation and video platforms. +- Ensure that the content you wish to embed allows iframe integration. + +### Limitations and Performance + +- **Screen Size**: Currently, the drawing screen size on the tablet is smaller than the presentations, which may affect how content is displayed. +- **Control**: There is no way to control the underlying presentation directly from the tablet. Users must use the side menu for navigation and control. +- This feature operates seamlessly, with no additional load on the reMarkable tablet, as all rendering is done in the client's browser. + +### Feedback and Contributions + +- As this is an experimental feature, your feedback is crucial for its development. Please share your experiences, suggestions, and any issues encountered using the GitHub issues section of this repository. + +--- + ## Technical Details ### Remarkable HTTP Server @@ -131,6 +166,9 @@ RK_HTTPS True or False true `GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 go build .` + + + ## Contributing I welcome contributions from the community to improve and enhance the reMarkable Screen Streaming Tool. If you have any ideas, bug reports, or feature requests, please submit them through the GitHub repository's issue tracker. diff --git a/client/canvasHandling.js b/client/canvasHandling.js index 114c8a5..1cb8e92 100644 --- a/client/canvasHandling.js +++ b/client/canvasHandling.js @@ -58,6 +58,8 @@ function renderCanvas(srcCanvas, dstCanvas) { // Clear the destination canvas ctxDst.clearRect(0, 0, w, h); + ctxDst.imageSmoothingEnabled = true; + if (rotate) { // Swap width and height for dstCanvas to accommodate rotated content diff --git a/client/index.html b/client/index.html index 6d4837e..15e5349 100644 --- a/client/index.html +++ b/client/index.html @@ -27,7 +27,9 @@
+
+ diff --git a/client/main.js b/client/main.js index f7ebd4d..1e85886 100644 --- a/client/main.js +++ b/client/main.js @@ -42,4 +42,19 @@ worker.onmessage = (event) => { } }; +window.onload = function() { + // Function to get the value of a query parameter by name + function getQueryParam(name) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(name); + } + + // Get the 'present' parameter from the URL + const presentURL = getQueryParam('present'); + + // Set the iframe source if the URL is available + if (presentURL) { + document.getElementById('content').src = presentURL; + } +}; diff --git a/client/style.css b/client/style.css index 5f1020e..7159995 100644 --- a/client/style.css +++ b/client/style.css @@ -6,7 +6,6 @@ body, html { } #container { - position: relative; width: 100%; height: 100%; display: flex; @@ -16,6 +15,7 @@ body, html { } #canvas { + position: fixed; max-width: 100%; max-height: 100%; } diff --git a/client/worker_stream_processing.js b/client/worker_stream_processing.js index 222c44c..b956078 100644 --- a/client/worker_stream_processing.js +++ b/client/worker_stream_processing.js @@ -69,6 +69,9 @@ async function initiateStream() { offset += 4; if (withColor) { switch (value) { + case 30: // red + imageData[offset+3] = 0; + break; case 10: // red imageData[offset] = 255; imageData[offset+1] = 0; @@ -101,10 +104,14 @@ async function initiateStream() { break; } } else { - imageData[offset] = value * 10; - imageData[offset+1] = value * 10; - imageData[offset+2] = value * 10; - imageData[offset+3] = 255; + if (value === 30) { + imageData[offset+3] = 0; + } else { + imageData[offset] = value * 10; + imageData[offset+1] = value * 10; + imageData[offset+2] = value * 10; + imageData[offset+3] = 255; + } } } // value is treated, wait for a count @@ -118,7 +125,7 @@ async function initiateStream() { // Instead of calling copyCanvasContent(), send the OffscreenCanvas to the main thread postMessage({ type: 'update', data: imageData }); - //} + //} //lastSum = currentSum; } diff --git a/docs/goMarkableStreamRecording.mp4 b/docs/goMarkableStreamRecording.mp4 new file mode 100644 index 0000000..e80561e Binary files /dev/null and b/docs/goMarkableStreamRecording.mp4 differ diff --git a/docs/gorgoniaExample.png b/docs/gorgoniaExample.png new file mode 100644 index 0000000..e1034ef Binary files /dev/null and b/docs/gorgoniaExample.png differ