Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ jobs:
with:
context: .
file: ./Dockerfile

- name: Push Docker image to Docker Hub
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker tag scalacast:latest ${{ secrets.DOCKER_USERNAME }}/scalacast:latest
docker push ${{ secrets.DOCKER_USERNAME }}/scalacast:latest
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build stage for Scala
FROM ubuntu:24.04 AS scala-build
FROM ubuntu:20.04 AS scala-build
WORKDIR /app

# Install Java and SBT dependencies
Expand All @@ -25,7 +25,7 @@ COPY src/scala ./src/scala/
RUN sbt compile

# Final runtime stage
FROM ubuntu:24.04
FROM ubuntu:20.04
WORKDIR /app

ENV NODE_NAME_1=node1@127.0.0.1 \
Expand Down
198 changes: 198 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -826,3 +826,201 @@ To run the project locally, follow these steps:

### Note
The `scripts/run_local.sh` and `scripts/run_local.bat` scripts are deprecated. Please use the `scripts/run_local.py` script for local testing and running the project.

## Webcam Test Site

The project is now ready for release as a site for testing webcam functionality. The webcam test site allows users to select different streaming protocols and camera inputs for testing purposes.

### Features
- Select different streaming protocols: Webcam, HLS, DASH, RTMP
- Choose camera inputs for different users and ports
- Display the selected camera input in a video element

### How to Use the Webcam Test Site
1. Open the `docs/index.html` file in a web browser.
2. Select a streaming protocol from the dropdown menu.
3. Choose a camera input for each user and port.
4. The selected camera input will be displayed in the video element.

### Example
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webcam Test - ScalaCast</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin: 0;
padding: 0;
}
video {
width: 80%;
max-width: 600px;
margin: 20px auto;
display: block;
}
select {
margin: 20px;
padding: 10px;
font-size: 16px;
}
</style>
</head>
<body>
<h1>Webcam Test</h1>
<select id="streamingOptions">
<option value="webcam">Webcam</option>
<option value="hls">HLS</option>
<option value="dash">DASH</option>
<option value="rtmp">RTMP</option>
</select>
<select id="user1Camera">
<option value="">Select Camera for User 1</option>
</select>
<select id="user2Camera">
<option value="">Select Camera for User 2</option>
</select>
<select id="port1Camera">
<option value="">Select Camera for Port 1</option>
</select>
<select id="port2Camera">
<option value="">Select Camera for Port 2</option>
</select>
<div id="selectedCameraInput">
<h2>Selected Camera Input</h2>
<video id="selectedCameraVideo" autoplay controls></video>
</div>
<video id="videoElement" autoplay controls></video>
<script>
const videoElement = document.getElementById('videoElement');
const streamingOptions = document.getElementById('streamingOptions');
const user1Camera = document.getElementById('user1Camera');
const user2Camera = document.getElementById('user2Camera');
const port1Camera = document.getElementById('port1Camera');
const port2Camera = document.getElementById('port2Camera');
const selectedCameraVideo = document.getElementById('selectedCameraVideo');

function getCameras() {
return navigator.mediaDevices.enumerateDevices()
.then(devices => devices.filter(device => device.kind === 'videoinput'));
}

function populateCameraOptions(selectElement, cameras) {
cameras.forEach(camera => {
const option = document.createElement('option');
option.value = camera.deviceId;
option.text = camera.label || `Camera ${selectElement.length + 1}`;
selectElement.appendChild(option);
});
}

getCameras().then(cameras => {
populateCameraOptions(user1Camera, cameras);
populateCameraOptions(user2Camera, cameras);
populateCameraOptions(port1Camera, cameras);
populateCameraOptions(port2Camera, cameras);
});

streamingOptions.addEventListener('change', function() {
const selectedOption = streamingOptions.value;
if (selectedOption === 'webcam') {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true })
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
})
.catch(function(error) {
console.error("Error accessing webcam: ", error);
});
} else {
console.error("getUserMedia not supported by this browser.");
}
} else if (selectedOption === 'hls') {
videoElement.src = 'path/to/hls/playlist.m3u8';
videoElement.play();
} else if (selectedOption === 'dash') {
videoElement.src = 'path/to/dash/manifest.mpd';
videoElement.play();
} else if (selectedOption === 'rtmp') {
videoElement.src = 'rtmp://localhost/live/stream';
videoElement.play();
}
});

user1Camera.addEventListener('change', function() {
const selectedCameraId = user1Camera.value;
if (selectedCameraId) {
navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: selectedCameraId } } })
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for User 1: ", error);
});
}
});

user2Camera.addEventListener('change', function() {
const selectedCameraId = user2Camera.value;
if (selectedCameraId) {
navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: selectedCameraId } } })
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for User 2: ", error);
});
}
});

port1Camera.addEventListener('change', function() {
const selectedCameraId = port1Camera.value;
if (selectedCameraId) {
navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: selectedCameraId } } })
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for Port 1: ", error);
});
}
});

port2Camera.addEventListener('change', function() {
const selectedCameraId = port2Camera.value;
if (selectedCameraId) {
navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: selectedCameraId } } })
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for Port 2: ", error);
});
}
});

// Initialize with webcam option
streamingOptions.value = 'webcam';
streamingOptions.dispatchEvent(new Event('change'));
</script>
<!-- Scala is used for the frontend -->
</body>
</html>
```
4 changes: 4 additions & 0 deletions config/sys.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@
{http, [
{port1, 8080},
{port2, 8081}
]},
{webcam_test_site, [
{streaming_protocols, ["webcam", "hls", "dash", "rtmp"]},
{camera_selections, ["user1", "user2", "port1", "port2"]}
]}
].
15 changes: 14 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Webcam Test - Scala Frontend</title>
<title>Webcam Test - ScalaCast</title>
<style>
body {
font-family: Arial, sans-serif;
Expand Down Expand Up @@ -44,6 +44,10 @@ <h1>Webcam Test</h1>
<select id="port2Camera">
<option value="">Select Camera for Port 2</option>
</select>
<div id="selectedCameraInput">
<h2>Selected Camera Input</h2>
<video id="selectedCameraVideo" autoplay controls></video>
</div>
<video id="videoElement" autoplay controls></video>
<script>
const videoElement = document.getElementById('videoElement');
Expand All @@ -52,6 +56,7 @@ <h1>Webcam Test</h1>
const user2Camera = document.getElementById('user2Camera');
const port1Camera = document.getElementById('port1Camera');
const port2Camera = document.getElementById('port2Camera');
const selectedCameraVideo = document.getElementById('selectedCameraVideo');

function getCameras() {
return navigator.mediaDevices.enumerateDevices()
Expand Down Expand Up @@ -108,6 +113,8 @@ <h1>Webcam Test</h1>
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for User 1: ", error);
Expand All @@ -122,6 +129,8 @@ <h1>Webcam Test</h1>
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for User 2: ", error);
Expand All @@ -136,6 +145,8 @@ <h1>Webcam Test</h1>
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for Port 1: ", error);
Expand All @@ -150,6 +161,8 @@ <h1>Webcam Test</h1>
.then(function(stream) {
videoElement.srcObject = stream;
videoElement.play();
selectedCameraVideo.srcObject = stream;
selectedCameraVideo.play();
})
.catch(function(error) {
console.error("Error accessing camera for Port 2: ", error);
Expand Down
Loading