Skip to content

Commit

Permalink
openvidu-server: allow only-audio broadcasting. Add new test
Browse files Browse the repository at this point in the history
  • Loading branch information
pabloFuente committed Apr 26, 2023
1 parent f5e18fc commit b40f120
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -716,8 +716,7 @@ public final static boolean IS_COMPOSED(OutputMode outputMode) {
* @hidden
*/
public final static Map<String, ?> removeNonBroadcastProperties(Map<String, ?> params) {
List<String> nonBroadcastProps = Arrays
.asList(new String[] { "outputMode", "name", "hasVideo", "ignoreFailedStreams" });
List<String> nonBroadcastProps = Arrays.asList(new String[] { "outputMode", "name", "ignoreFailedStreams" });
nonBroadcastProps.forEach(p -> params.remove(p));
return params;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,67 @@ void sucessfullBroadcastTest() throws Exception {
}
}

@Test
@DisplayName("Successfull only video only audio broadcast Test")
void sucessfullBroadcastOnlyVideoOnlyAudioTest() throws Exception {

log.info("Successfull only video only audio broadcast Test");

try {
String BROADCAST_IP = TestUtils.startRtmpServer();

OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
user.getDriver().findElement(By.id("add-user-btn")).click();
user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER);
user.getEventManager().waitUntilEventReaches("streamCreated", 1);
user.getEventManager().waitUntilEventReaches("streamPlaying", 1);

user.getDriver().findElement(By.id("session-api-btn-0")).click();
Thread.sleep(750);
WebElement broadcastUrlField = user.getDriver().findElement(By.id("broadcasturl-id-field"));
broadcastUrlField.clear();
broadcastUrlField.sendKeys("rtmp://" + BROADCAST_IP + "/live");
user.getDriver().findElement(By.id("broadcast-properties-btn")).click();
Thread.sleep(500);

// Only video
user.getDriver().findElement(By.id("rec-hasaudio-checkbox")).click();
Thread.sleep(500);

user.getDriver().findElement(By.id("start-broadcast-btn")).click();
user.getWaiter().until(
ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Broadcast started"));
user.getEventManager().waitUntilEventReaches("broadcastStarted", 1);

checkRtmpRecordingIsFine(30, RecordingUtils::checkVideoAverageRgbGreen);

user.getDriver().findElement(By.id("stop-broadcast-btn")).click();
user.getWaiter().until(
ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Broadcast stopped"));
user.getEventManager().waitUntilEventReaches("broadcastStopped", 1);

// Only audio
user.getDriver().findElement(By.id("rec-hasaudio-checkbox")).click();
user.getDriver().findElement(By.id("rec-hasvideo-checkbox")).click();
Thread.sleep(500);

user.getDriver().findElement(By.id("start-broadcast-btn")).click();
user.getWaiter().until(
ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Broadcast started"));
user.getEventManager().waitUntilEventReaches("broadcastStarted", 1);

user.getDriver().findElement(By.id("stop-broadcast-btn")).click();
user.getWaiter().until(
ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Broadcast stopped"));
user.getEventManager().waitUntilEventReaches("broadcastStopped", 1);

gracefullyLeaveParticipants(user, 1);

} finally {
TestUtils.stopRtmpServer();
}
}

@Test
@DisplayName("Wrong broadcast Test")
void wrongBroadcastTest() throws Exception {
Expand Down Expand Up @@ -2911,6 +2972,9 @@ void wrongBroadcastTest() throws Exception {
// 422
body = "{'session':'TestSession','broadcastUrl':'rtmp://" + BROADCAST_IP + "/live','resolution':'99x1280'}";
restClient.rest(HttpMethod.POST, "/openvidu/api/broadcast/start", body, 422);
body = "{'session':'TestSession','broadcastUrl':'rtmp://" + BROADCAST_IP
+ "/live','hasAudio':false,'hasVideo':false}";
restClient.rest(HttpMethod.POST, "/openvidu/api/broadcast/start", body, 422);
// 500 (Connection refused)
body = "{'session':'TestSession','broadcastUrl':'rtmps://" + BROADCAST_IP + "/live'}";
String errorResponse = restClient.commonRestString(HttpMethod.POST, "/openvidu/api/broadcast/start", body,
Expand Down Expand Up @@ -3003,7 +3067,7 @@ void customLayoutBroadcastTest() throws Exception {
Map<String, Object> config = Map.of("OPENVIDU_PRO_SPEECH_TO_TEXT", "disabled", "OPENVIDU_RECORDING", true,
"OPENVIDU_RECORDING_CUSTOM_LAYOUT", "/opt/openvidu/test-layouts");
restartOpenViduServer(config);

final String SESSION_NAME = "CUSTOM_LAYOUT_SESSION";

OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
Expand Down Expand Up @@ -3085,7 +3149,16 @@ private void checkRtmpRecordingIsFine(long secondsTimeout, Function<Map<String,
// Analyze most recent file (there can be more than one in the path)
File[] files = new File(broadcastRecordingPath + "/tmp").listFiles();
Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
commandLine.executeCommand("ffmpeg -i " + files[0].getAbsolutePath() + " -vframes 1 "
// This fixes corrupted video files
String fixedFile = broadcastRecordingPath + "/tmp/test.flv";
commandLine.executeCommand(
"ffmpeg -i " + files[0].getAbsolutePath() + " -acodec copy -vcodec copy " + fixedFile, 10);
// This obtains the middle duration of the video
String videoDuration = commandLine.executeCommand(
"ffprobe -loglevel error -of csv=p=0 -show_entries format=duration " + fixedFile, 3);
float halfDuration = (float) (Float.parseFloat(videoDuration) * 0.5);
// This retrieves the frame from the middle of the video
commandLine.executeCommand("ffmpeg -ss " + halfDuration + " -i " + fixedFile + " -vframes 1 "
+ broadcastRecordingPath + "/tmp/rtmp-screenshot.jpg", 3);
File screenshot = new File(broadcastRecordingPath + "/tmp/rtmp-screenshot.jpg");
if (screenshot.exists() && screenshot.isFile() && screenshot.length() > 0 && screenshot.canRead()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
</mat-form-field>
<div class="inner-text-input mat-form-field">
<mat-checkbox id="rec-hasaudio-checkbox" [(ngModel)]="recordingProperties.hasAudio">Has audio</mat-checkbox>
<mat-checkbox *ngIf="!isBroadcast" id="rec-hasvideo-checkbox" [(ngModel)]="recordingProperties.hasVideo">Has
video</mat-checkbox>
<mat-checkbox id="rec-hasvideo-checkbox" [(ngModel)]="recordingProperties.hasVideo">Has video</mat-checkbox>
<mat-checkbox *ngIf="recordingProperties.outputMode === 'INDIVIDUAL'" id="rec-ignorefailedstreams-checkbox"
[(ngModel)]="recordingProperties.ignoreFailedStreams">Ignore failed streams</mat-checkbox>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,11 @@ export class RecordingPropertiesComponent {
@Input()
isBroadcast = false;

recMode = Recording.OutputMode;
recLayouts = RecordingLayout;

getRecordingProperties: RecordingProperties;
@Output() recordingPropertiesChange: EventEmitter<RecordingProperties> = new EventEmitter<RecordingProperties>();

@Input()
get recordingProperties(): RecordingProperties {
return this.getRecordingProperties;
}
recordingProperties: RecordingProperties;

set recordingProperties(value: RecordingProperties) {
this.getRecordingProperties = value;
this.recordingPropertiesChange.emit(this.getRecordingProperties);
}
recMode = Recording.OutputMode;
recLayouts = RecordingLayout;

enumToArray(enumerator: any) {
return Object.keys(enumerator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ <h2 mat-dialog-title>API REST</h2>
aria-label="Recording properties">
{{recPropertiesIcon}}</mat-icon>
</button>
<app-recording-properties *ngIf="showRecProperties" [(recordingProperties)]="recordingProperties">
<app-recording-properties *ngIf="showRecProperties" [isBroadcast]="false"
[recordingProperties]="recordingProperties">
</app-recording-properties>
</div>
<div>
Expand Down Expand Up @@ -106,7 +107,8 @@ <h2 mat-dialog-title>API REST</h2>
<mat-icon style="font-size: 18px; line-height: 18px; width: 18px; height: 18px"
aria-label="Broadcast properties">{{broadcastPropertiesIcon}}</mat-icon>
</button>
<app-recording-properties *ngIf="showBroadcastProperties" [isBroadcast]="true" [(recordingProperties)]="broadcastProperties">
<app-recording-properties *ngIf="showBroadcastProperties" [isBroadcast]="true"
[recordingProperties]="broadcastProperties">
</app-recording-properties>
</div>

Expand All @@ -120,6 +122,6 @@ <h2 mat-dialog-title>API REST</h2>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button id="close-dialog-btn"
[mat-dialog-close]="{session: session, recordingProperties: recordingProperties}">CLOSE</button>
[mat-dialog-close]="{session: session, recordingProperties: recordingProperties, broadcastProperties: broadcastProperties}">CLOSE</button>
</mat-dialog-actions>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,15 @@ export class SessionApiDialogComponent {
toggleRecProperties() {
this.showRecProperties = !this.showRecProperties;
this.recPropertiesIcon = this.showRecProperties ? 'remove_circle' : 'add_circle';
this.showBroadcastProperties = false;
this.broadcastPropertiesIcon = 'add_circle';
}

toggleBroadcastProperties() {
this.showBroadcastProperties = !this.showBroadcastProperties;
this.broadcastPropertiesIcon = this.showBroadcastProperties ? 'remove_circle' : 'add_circle';
this.showRecProperties = false;
this.recPropertiesIcon = 'add_circle';
}

changedNumIceServers(numIceServers: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <h2 mat-dialog-title>Session properties</h2>
</mat-select>
</mat-form-field>

<app-recording-properties [(recordingProperties)]="sessionProperties.defaultRecordingProperties">
<app-recording-properties [recordingProperties]="sessionProperties.defaultRecordingProperties">
</app-recording-properties>

<div id="allow-transcoding-checkbox-div">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,13 +649,15 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
}

openSessionApiDialog() {
const defaultRecordingProperties = JSON.parse(JSON.stringify(this.sessionProperties.defaultRecordingProperties));
const defaultBroadcastProperties = JSON.parse(JSON.stringify(this.sessionProperties.defaultRecordingProperties));
const dialogRef = this.dialog.open(SessionApiDialogComponent, {
data: {
openVidu: !!this.OV_NodeClient ? this.OV_NodeClient : new OpenViduAPI(this.openviduUrl, this.openviduSecret),
session: this.sessionAPI,
sessionId: !!this.session ? this.session.sessionId : this.sessionName,
recordingProperties: !!this.recordingProperties ? this.recordingProperties : this.sessionProperties.defaultRecordingProperties,
broadcastProperties: !!this.broadcastProperties ? this.broadcastProperties : this.sessionProperties.defaultRecordingProperties
recordingProperties: !!this.recordingProperties ? this.recordingProperties : defaultRecordingProperties,
broadcastProperties: !!this.broadcastProperties ? this.broadcastProperties : defaultBroadcastProperties
},
disableClose: true
});
Expand All @@ -665,6 +667,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
delete this.sessionAPI;
}
this.recordingProperties = result.recordingProperties;
this.broadcastProperties = result.broadcastProperties;
document.getElementById('session-api-btn-' + this.index).classList.remove('cdk-program-focused');
});
}
Expand Down

0 comments on commit b40f120

Please sign in to comment.