001/* 002 * Copyright 2024 Vonage 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.vonage.client.voice.ncco; 017 018import com.fasterxml.jackson.annotation.JsonProperty; 019import com.vonage.client.JsonableBaseObject; 020import java.util.Arrays; 021import java.util.Collection; 022 023/** 024 * An NCCO record action which allows for the call to be recorded. 025 * <p> 026 * 027 * The record action is asynchronous. Recording starts when the record action is executed in the NCCO and finishes 028 * when the synchronous condition in the action is met. That is, endOnSilence, timeOut or endOnKey. If you do not 029 * set a synchronous condition, the Voice API immediately executes the next NCCO without recording. 030 */ 031public final class RecordAction extends JsonableBaseObject implements Action { 032 private static final String ACTION = "record"; 033 034 private RecordingFormat format; 035 private Integer endOnSilence, timeOut, channels; 036 private Character endOnKey; 037 private Boolean beepStart; 038 private Collection<String> eventUrl; 039 private EventMethod eventMethod; 040 private SplitRecording split; 041 private TranscriptionSettings transcription; 042 043 RecordAction() {} 044 045 private RecordAction(Builder builder) { 046 format = builder.format; 047 endOnSilence = builder.endOnSilence; 048 endOnKey = builder.endOnKey; 049 timeOut = builder.timeOut; 050 beepStart = builder.beepStart; 051 eventUrl = builder.eventUrl; 052 eventMethod = builder.eventMethod; 053 // Split conversation must be enabled for multiple channels. Checked during construction to avoid 054 // method-chaining state confusion. 055 split = (builder.channels != null && builder.channels > 1) ? SplitRecording.CONVERSATION : builder.split; 056 channels = builder.channels; 057 transcription = builder.transcription; 058 } 059 060 @Override 061 public String getAction() { 062 return ACTION; 063 } 064 065 @JsonProperty("format") 066 public RecordingFormat getFormat() { 067 return format; 068 } 069 070 @JsonProperty("endOnSilence") 071 public Integer getEndOnSilence() { 072 return endOnSilence; 073 } 074 075 @JsonProperty("endOnKey") 076 public Character getEndOnKey() { 077 return endOnKey; 078 } 079 080 @JsonProperty("timeOut") 081 public Integer getTimeOut() { 082 return timeOut; 083 } 084 085 @JsonProperty("beepStart") 086 public Boolean getBeepStart() { 087 return beepStart; 088 } 089 090 @JsonProperty("eventUrl") 091 public Collection<String> getEventUrl() { 092 return eventUrl; 093 } 094 095 @JsonProperty("eventMethod") 096 public EventMethod getEventMethod() { 097 return eventMethod; 098 } 099 100 @JsonProperty("split") 101 public SplitRecording getSplit() { 102 return split; 103 } 104 105 @JsonProperty("channels") 106 public Integer getChannels() { 107 return channels; 108 } 109 110 @JsonProperty("transcription") 111 public TranscriptionSettings getTranscription() { 112 return transcription; 113 } 114 115 /** 116 * Entrypoint for constructing an instance of this class. 117 * 118 * @return A new Builder. 119 */ 120 public static Builder builder() { 121 return new Builder(); 122 } 123 124 /** 125 * Builder for a RecordAction. All fields are optional. 126 */ 127 public static class Builder { 128 private RecordingFormat format; 129 private Character endOnKey; 130 private Integer timeOut, channels, endOnSilence; 131 private Boolean beepStart; 132 private Collection<String> eventUrl; 133 private EventMethod eventMethod; 134 private SplitRecording split; 135 private TranscriptionSettings transcription; 136 137 Builder() {} 138 139 /** 140 * @param format Record the Call in a specific {@link RecordingFormat}. 141 * <p> 142 * The default value is {@link RecordingFormat#MP3}, or {@link RecordingFormat#WAV} when recording 143 * more than 2 channels. 144 * 145 * @return This builder. 146 */ 147 public Builder format(RecordingFormat format) { 148 this.format = format; 149 return this; 150 } 151 152 /** 153 * @param endOnSilence Stop recording after n seconds of silence. Once the recording is stopped the recording 154 * data is sent to event_url. The range of possible values is between 3 and 10 inclusively. 155 * 156 * @return This builder. 157 */ 158 public Builder endOnSilence(Integer endOnSilence) { 159 this.endOnSilence = endOnSilence; 160 return this; 161 } 162 163 /** 164 * @param endOnKey Stop recording when a digit is pressed on the handset. Possible values are: *, # or any 165 * single digit e.g. 9 166 * 167 * @return This builder. 168 */ 169 public Builder endOnKey(Character endOnKey) { 170 this.endOnKey = endOnKey; 171 return this; 172 } 173 174 /** 175 * @param timeOut The maximum length of a recording in seconds. One the recording is stopped the recording data 176 * is sent to event_url. The range of possible values is between 3 seconds and 7200 seconds (2 177 * hours) 178 * 179 * @return This builder. 180 */ 181 public Builder timeOut(Integer timeOut) { 182 this.timeOut = timeOut; 183 return this; 184 } 185 186 /** 187 * @param beepStart Set to true to play a beep when a recording starts 188 * 189 * @return This builder. 190 */ 191 public Builder beepStart(Boolean beepStart) { 192 this.beepStart = beepStart; 193 return this; 194 } 195 196 /** 197 * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished. 198 * If the message recording is hosted by Vonage, this webhook contains the URL you need to 199 * download the recording and other meta data. 200 * 201 * @return This builder. 202 */ 203 public Builder eventUrl(Collection<String> eventUrl) { 204 this.eventUrl = eventUrl; 205 return this; 206 } 207 208 /** 209 * @param eventUrl The URL to the webhook endpoint that is called asynchronously when a recording is finished. 210 * If the message recording is hosted by Vonage, this webhook contains the URL you need to 211 * download the recording and other meta data. 212 * 213 * @return This builder. 214 */ 215 public Builder eventUrl(String... eventUrl) { 216 return eventUrl(Arrays.asList(eventUrl)); 217 } 218 219 /** 220 * @param eventMethod The HTTP method used to make the request to eventUrl. The default value is POST. 221 * 222 * @return This builder. 223 */ 224 public Builder eventMethod(EventMethod eventMethod) { 225 this.eventMethod = eventMethod; 226 return this; 227 } 228 229 /** 230 * @param split Record the sent and received audio in separate channels of a stereo recording-set to {@link 231 * SplitRecording#CONVERSATION} to enable this. 232 * 233 * @return This builder. 234 */ 235 public Builder split(SplitRecording split) { 236 this.split = split; 237 return this; 238 } 239 240 /** 241 * @param channels The number of channels to record (maximum 32). If the number of participants exceeds channels 242 * any additional participants will be added to the last channel in file. {@link #split} will be 243 * set to {@link SplitRecording#CONVERSATION} during the build process if channels is greater 244 * than 1. 245 * 246 * @return This builder. 247 */ 248 public Builder channels(Integer channels) { 249 this.channels = channels; 250 return this; 251 } 252 253 /** 254 * Set this parameter to a non-null value to transcribe the recording. 255 * 256 * @param transcription The transcription settings. 257 * 258 * @return This builder. 259 * @since 8.2.0 260 */ 261 public Builder transcription(TranscriptionSettings transcription) { 262 this.transcription = transcription; 263 return this; 264 } 265 266 /** 267 * Builds the RecordAction. 268 * 269 * @return A new RecordAction object from the stored builder options. 270 */ 271 public RecordAction build() { 272 return new RecordAction(this); 273 } 274 } 275}