mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: allow only-audio broadcasting. Add new test
parent
f5e18fc11d
commit
b40f120efa
|
@ -716,8 +716,7 @@ public class RecordingProperties {
|
|||
* @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;
|
||||
}
|
||||
|
|
|
@ -2867,6 +2867,67 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
}
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
@ -2911,6 +2972,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
// 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,
|
||||
|
@ -3003,7 +3067,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
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");
|
||||
|
@ -3085,7 +3149,16 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
|||
// 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()) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -11,22 +11,12 @@ export class RecordingPropertiesComponent {
|
|||
@Input()
|
||||
isBroadcast = false;
|
||||
|
||||
@Input()
|
||||
recordingProperties: RecordingProperties;
|
||||
|
||||
recMode = Recording.OutputMode;
|
||||
recLayouts = RecordingLayout;
|
||||
|
||||
getRecordingProperties: RecordingProperties;
|
||||
@Output() recordingPropertiesChange: EventEmitter<RecordingProperties> = new EventEmitter<RecordingProperties>();
|
||||
|
||||
@Input()
|
||||
get recordingProperties(): RecordingProperties {
|
||||
return this.getRecordingProperties;
|
||||
}
|
||||
|
||||
set recordingProperties(value: RecordingProperties) {
|
||||
this.getRecordingProperties = value;
|
||||
this.recordingPropertiesChange.emit(this.getRecordingProperties);
|
||||
}
|
||||
|
||||
enumToArray(enumerator: any) {
|
||||
return Object.keys(enumerator);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,8 @@
|
|||
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>
|
||||
|
@ -106,7 +107,8 @@
|
|||
<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>
|
||||
|
||||
|
@ -120,6 +122,6 @@
|
|||
</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>
|
|
@ -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) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</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">
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue