aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-09-14 16:22:43 +0800
committerMistivia <i@mistivia.com>2025-09-14 16:22:43 +0800
commitaadfa7ff09334f0b2b81cec19afef53b2a3fd9df (patch)
treef2fa93f34f607c8bd889268ea632633d08a34142
parentc5c3ec74e8f39995a060e105e95db1d8d8908180 (diff)
add s3 clear and readme
-rw-r--r--Readme.md47
-rw-r--r--s3_client.cpp44
-rw-r--r--s3_client.h2
-rw-r--r--s3_worker.c2
4 files changed, 91 insertions, 4 deletions
diff --git a/Readme.md b/Readme.md
index 8405cdd..7871188 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,7 +1,48 @@
# EZLive: Self-hosted Serverless Livestream
-(Still work-in-progress)
-
EZLive is a minimal self-hosted livestream solution built on top of S3-compatible object storage.
-It runs a local RTMP server, receive live video, turns it into HLS segments (.m3u8 + .ts) and serves them as static files through S3 or a CDN. No dedicated streaming server is required — everything runs serverless. \ No newline at end of file
+It runs a local RTMP server, receive live video, turns it into HLS segments (.m3u8 + .ts) and serves them as static files through any S3-compatible OSS. No dedicated streaming server is required — everything runs serverlessly. Then you can easily setup a HTML5 HLS player to watch the stream.
+
+# Build
+
+Install dependencies:
+
+- FFMpeg (libavformat, libavutil, libavcodec)
+- AWS C++ SDK (libaws-cpp-sdk-core, libaws-cpp-sdk-s3)
+
+Build:
+
+ make
+
+
+# Usage
+
+Setup a S3-compatible OSS bucket, for example, Cloudflare R2, AWS S3, Minio, DigitalOcean, etc.
+
+Then create a config file `config`:
+
+```
+listening_addr=127.0.0.1
+listening_port=1935
+bucket=YOUR_BUCKET_NAME
+endpoint=https://your-oss.com
+s3_path=ezlive/
+access_key=YOUR_S3_ACCESS_KEY
+secret_key=YOUR_S3_SECRET_KEY
+region=auto
+```
+
+In the dashboard of your OSS cloud provider, add the domain name of your web HLS player to CORS setting. If you don't know how to setup a web HLS player, just add `https://mistivia.github.io`.
+
+Start EZLive:
+
+```
+./ezlive
+```
+
+Open OBS, streaming to `rtmp://127.0.0.1/live`, no streaming key needed.
+
+Then use a HLS player to load `https://YOUR_BUCKET_NAME.our-oss.com/ezlive/stream.m3u8` to watch the stream.
+
+If you don't know how to setup a HLS player, then make sure you have added `https://mistivia.github.io` in your OSS's CORS setting, then open `https://mistivia.github.io/ezlive#https://YOUR_BUCKET_NAME.our-oss.com/ezlive/stream.m3u8`.
diff --git a/s3_client.cpp b/s3_client.cpp
index 4076b1c..668e902 100644
--- a/s3_client.cpp
+++ b/s3_client.cpp
@@ -8,7 +8,9 @@
#include <aws/s3/S3Client.h>
#include <aws/s3/model/PutObjectRequest.h>
#include <aws/s3/model/DeleteObjectRequest.h>
+#include <aws/s3/model/DeleteObjectsRequest.h>
#include <aws/core/auth/AWSCredentials.h>
+#include <aws/s3/model/ListObjectsV2Request.h>
#include "ezlive_config.h"
@@ -76,4 +78,46 @@ void S3Client_delete(const char *object_name) {
} else {
fprintf(stdout, "Successfully deleted the object: %s\n", object_name);
}
+}
+
+void S3Client_clear() {
+ Aws::S3::Model::ListObjectsV2Request list_req;
+ list_req.WithBucket(ezlive_config->bucket).WithPrefix(ezlive_config->s3_path);
+
+ auto list_outcome = s3client->ListObjectsV2(list_req);
+ if (!list_outcome.IsSuccess()) {
+ fprintf(stderr, "ListObjectsV2 error: %s\n",
+ list_outcome.GetError().GetMessage().c_str());
+ return;
+ }
+
+ Aws::Vector<Aws::S3::Model::ObjectIdentifier> objects_to_delete;
+
+ for (const auto& obj : list_outcome.GetResult().GetContents()) {
+ auto key = obj.GetKey();
+ if (key.size() >= 3 && key.substr(key.size() - 3) == ".ts") {
+ Aws::S3::Model::ObjectIdentifier oid;
+ oid.SetKey(key);
+ objects_to_delete.push_back(oid);
+ printf("Marking for delete: %s\n", key.c_str());
+ }
+ }
+ if (!objects_to_delete.empty()) {
+ Aws::S3::Model::DeleteObjectsRequest del_req;
+ del_req.WithBucket(ezlive_config->bucket)
+ .WithDelete(Aws::S3::Model::Delete().WithObjects(objects_to_delete));
+
+ auto del_outcome = s3client->DeleteObjects(del_req);
+ if (!del_outcome.IsSuccess()) {
+ std::cerr << "DeleteObjects error: "
+ << del_outcome.GetError().GetMessage() << std::endl;
+ return;
+ } else {
+ std::cout << "Deleted "
+ << del_outcome.GetResult().GetDeleted().size()
+ << " objects." << std::endl;
+ }
+ } else {
+ std::cout << "No .ts files found. No need to clear." << std::endl;
+ }
} \ No newline at end of file
diff --git a/s3_client.h b/s3_client.h
index 43d4208..f42e549 100644
--- a/s3_client.h
+++ b/s3_client.h
@@ -11,6 +11,8 @@ void S3Client_put(const char *filename, const char *object_name);
void S3Client_delete(const char *object_name);
+void S3Client_clear();
+
#ifdef __cplusplus
}
#endif
diff --git a/s3_worker.c b/s3_worker.c
index a6ae2ab..6482224 100644
--- a/s3_worker.c
+++ b/s3_worker.c
@@ -21,7 +21,7 @@ void exec_s3_task(void *vtask) {
snprintf(obj_name_buf, 255, "%s%s", ezlive_config->s3_path, task->remote_name);
S3Client_delete(obj_name_buf);
} else if (task->task_type == kClearTask) {
- // TODO
+ S3Client_clear();
} else {
fprintf(stderr, "unknown task type.\n");
}