Skip to content

Commit

Permalink
dynamic sub folder for hls upload with maintrackId and streamId varia…
Browse files Browse the repository at this point in the history
…bles
  • Loading branch information
lastpeony committed Nov 26, 2024
1 parent e2688b3 commit 873bc7d
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 46 deletions.
43 changes: 38 additions & 5 deletions src/main/java/io/antmedia/muxer/HLSMuxer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static org.bytedeco.ffmpeg.global.avcodec.*;
import static org.bytedeco.ffmpeg.global.avformat.avformat_alloc_output_context2;
import static org.bytedeco.ffmpeg.global.avutil.*;
import static org.bytedeco.ffmpeg.global.avutil.AV_OPT_SEARCH_CHILDREN;

import java.io.File;
import java.io.IOException;
Expand All @@ -15,10 +14,9 @@
import org.bytedeco.ffmpeg.avcodec.*;
import org.bytedeco.ffmpeg.avformat.AVFormatContext;
import org.bytedeco.ffmpeg.avformat.AVStream;
import org.bytedeco.ffmpeg.avutil.AVDictionary;
import org.bytedeco.ffmpeg.avutil.AVRational;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avformat;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacpp.BytePointer;
import org.red5.server.api.scope.IScope;
import org.slf4j.Logger;
Expand Down Expand Up @@ -61,6 +59,7 @@ public class HLSMuxer extends Muxer {
private String s3StreamsFolderPath = "streams";
private boolean uploadHLSToS3 = true;
private String segmentFilename;
private String mainTrackId = null;

/**
* HLS Segment Type. It can be "mpegts" or "fmp4"
Expand Down Expand Up @@ -134,14 +133,14 @@ public void setHlsParameters(String hlsListSize, String hlsTime, String hlsPlayL
/**
* {@inheritDoc}
*/
@Override
public void init(IScope scope, String name, int resolutionHeight, String subFolder, int bitrate) {
public void init(IScope scope, String name, int resolutionHeight, String subFolder, int bitrate, String mainTrackId) {
if (!isInitialized) {

super.init(scope, name, resolutionHeight, subFolder, bitrate);

streamId = name;
this.subFolder = subFolder;
this.mainTrackId = mainTrackId;
options.put("hls_list_size", hlsListSize);
options.put("hls_time", hlsTime);

Expand Down Expand Up @@ -209,12 +208,38 @@ public String getOutputURL()
return super.getOutputURL();
}

public String getCustomHeaderStr() {
String customHeaderStr = "";

if (mainTrackId != null) {
customHeaderStr += "mainTrackId: " + mainTrackId + "\r\n";
}

if (streamId != null) {
customHeaderStr += "streamId: " + streamId + "\r\n";
}

return customHeaderStr;
}

public AVFormatContext getOutputFormatContext() {
if (outputFormatContext == null) {

outputFormatContext= new AVFormatContext(null);
int ret = avformat_alloc_output_context2(outputFormatContext, null, format, getOutputURL());

if((StringUtils.isNotBlank(httpEndpoint))) {
AVDictionary options = new AVDictionary();
String customHeaderStr = getCustomHeaderStr();
if(StringUtils.isNotBlank(customHeaderStr)){

av_dict_set(options, "headers", customHeaderStr, 0);
av_opt_set_dict2(outputFormatContext.priv_data(), options, 0);

}
av_dict_free(options);
}

if (ret < 0) {
logger.info("Could not create output context for {}", getOutputURL());
return null;
Expand Down Expand Up @@ -634,4 +659,12 @@ protected synchronized void clearResource() {
public ByteBuffer getPendingSEIData() {
return pendingSEIData;
}

public String getMainTrackId() {
return mainTrackId;
}

public void setMainTrackId(String mainTrackId) {
this.mainTrackId = mainTrackId;
}
}
42 changes: 40 additions & 2 deletions src/main/java/io/antmedia/servlet/UploadHLSChunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
Expand All @@ -11,6 +13,7 @@
import jakarta.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bytedeco.ffmpeg.avutil.AVDictionary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
Expand All @@ -23,10 +26,11 @@
import io.antmedia.muxer.Muxer;
import io.antmedia.storage.StorageClient;

import static io.antmedia.muxer.Muxer.DATE_TIME_PATTERN;

@MultipartConfig
public class UploadHLSChunk extends HttpServlet {


private static final long serialVersionUID = 1L;

protected static Logger logger = LoggerFactory.getLogger(UploadHLSChunk.class);
Expand Down Expand Up @@ -138,7 +142,41 @@ else if (event.getEventType() == ProgressEventType.TRANSFER_COMPLETED_EVENT)
public static String getS3Key(HttpServletRequest req, AppSettings appSettings) {
//No need have File.separator between the below strings because req.getPathInfo() starts with "/"
//req.getPathInfo(); includes only the part after /hls-upload/. In other words, just {SUB_FOLDER} + (M3U8 or TS files)
return Muxer.replaceDoubleSlashesWithSingleSlash(appSettings.getS3StreamsFolderPath() + File.separator + req.getPathInfo());

String mainTrackId = req.getHeader("mainTrackId");
String streamId = req.getHeader("streamId");

return Muxer.replaceDoubleSlashesWithSingleSlash(getExtendedS3StreamsFolderPath(mainTrackId, streamId, appSettings.getS3StreamsFolderPath()) + File.separator + req.getPathInfo());
}

public static String getExtendedS3StreamsFolderPath(String mainTrackId, String streamId, String s3StreamsFolder) {
if (s3StreamsFolder == null) {
return "";
}

String result = s3StreamsFolder;

if (mainTrackId == null) {
result = result.replace("%m/", "")
.replace("/%m", "")
.replace("%m", "");
} else {
result = result.replace("%m", mainTrackId);
}

if (streamId == null) {
result = result.replace("%s/", "")
.replace("/%s", "")
.replace("%s", "");
} else {
result = result.replace("%s", streamId);
}

result = result.replaceAll("//+", "/");

result = result.trim().replaceAll("^/+|/+$", "");

return result;
}

}
Loading

0 comments on commit 873bc7d

Please sign in to comment.