VideoEditor.java revision fdacc8be92cd36f712cfdb0fcf9b0e847f8eeb58
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.media.videoeditor; 18 19import java.io.IOException; 20import java.util.List; 21import java.util.concurrent.CancellationException; 22 23import android.view.SurfaceHolder; 24 25/** 26 * This is the interface implemented by classes which provide video editing 27 * functionality. The VideoEditor implementation class manages all input and 28 * output files. Unless specifically mentioned, methods are blocking. A 29 * typical editing session may consist of the following sequence of operations: 30 * 31 * <ul> 32 * <li>Add a set of MediaItems</li> 33 * <li>Apply a set of Transitions between MediaItems</li> 34 * <li>Add Effects and Overlays to media items</li> 35 * <li>Preview the movie at any time</li> 36 * <li>Save the VideoEditor implementation class internal state</li> 37 * <li>Release the VideoEditor implementation class instance by invoking 38 * {@link #release()} 39 * </ul> 40 * The internal VideoEditor state consists of the following elements: 41 * <ul> 42 * <li>Ordered & trimmed MediaItems</li> 43 * <li>Transition video clips</li> 44 * <li>Overlays</li> 45 * <li>Effects</li> 46 * <li>Audio waveform for the background audio and MediaItems</li> 47 * <li>Project thumbnail</li> 48 * <li>Last exported movie.</li> 49 * <li>Other project specific data such as the current aspect ratio.</li> 50 * </ul> 51 * {@hide} 52 */ 53public interface VideoEditor { 54 // The file name of the project thumbnail 55 public static final String THUMBNAIL_FILENAME = "thumbnail.jpg"; 56 57 // Use this value instead of the specific end of the storyboard timeline 58 // value. 59 public final static int DURATION_OF_STORYBOARD = -1; 60 61 /** 62 * This listener interface is used by the VideoEditor to emit preview 63 * progress notifications. This callback should be invoked after the 64 * number of frames specified by 65 * {@link #startPreview(SurfaceHolder surfaceHolder, long fromMs, 66 * int callbackAfterFrameCount, PreviewProgressListener listener)} 67 */ 68 public interface PreviewProgressListener { 69 /** 70 * This method notifies the listener of the current time position while 71 * previewing a project. 72 * 73 * @param videoEditor The VideoEditor instance 74 * @param timeMs The current preview position (expressed in milliseconds 75 * since the beginning of the storyboard timeline). 76 * @param end true if the end of the timeline was reached 77 */ 78 public void onProgress(VideoEditor videoEditor, long timeMs, boolean end); 79 } 80 81 /** 82 * This listener interface is used by the VideoEditor to emit export status 83 * notifications. 84 * {@link #export(String filename, ExportProgressListener listener, int height, int bitrate)} 85 */ 86 public interface ExportProgressListener { 87 /** 88 * This method notifies the listener of the progress status of a export 89 * operation. 90 * 91 * @param videoEditor The VideoEditor instance 92 * @param filename The name of the file which is in the process of being 93 * exported. 94 * @param progress The progress in %. At the beginning of the export, this 95 * value is set to 0; at the end, the value is set to 100. 96 */ 97 public void onProgress(VideoEditor videoEditor, String filename, int progress); 98 } 99 100 /** 101 * @return The path where the VideoEditor stores all files related to the 102 * project 103 */ 104 public String getPath(); 105 106 /** 107 * This method releases all in-memory resources used by the VideoEditor 108 * instance. All pending operations such as preview, export and extract 109 * audio waveform must be canceled. 110 */ 111 public void release(); 112 113 /** 114 * Persist the current internal state of VideoEditor to the project path. 115 * The VideoEditor state may be restored by invoking the 116 * {@link VideoEditorFactory#load(String)} method. This method does not 117 * release the internal in-memory state of the VideoEditor. To release 118 * the in-memory state of the VideoEditor the {@link #release()} method 119 * must be invoked. 120 * 121 * Pending transition generations must be allowed to complete before the 122 * state is saved. 123 * Pending audio waveform generations must be allowed to complete. 124 * Pending export operations must be allowed to continue. 125 */ 126 public void save() throws IOException; 127 128 /** 129 * Create the output movie based on all media items added and the applied 130 * storyboard items. This method can take a long time to execute and is 131 * blocking. The application will receive progress notifications via the 132 * ExportProgressListener. Specific implementations may not support multiple 133 * simultaneous export operations. 134 * 135 * Note that invoking methods which would change the contents of the output 136 * movie throw an IllegalStateException while an export operation is 137 * pending. 138 * 139 * @param filename The output file name (including the full path) 140 * @param height The height of the output video file. The supported values 141 * for height are described in the MediaProperties class, for 142 * example: HEIGHT_480. The width will be automatically 143 * computed according to the aspect ratio provided by 144 * {@link #setAspectRatio(int)} 145 * @param bitrate The bitrate of the output video file. This is approximate 146 * value for the output movie. Supported bitrate values are 147 * described in the MediaProperties class for example: 148 * BITRATE_384K 149 * @param listener The listener for progress notifications. Use null if 150 * export progress notifications are not needed. 151 * 152 * @throws IllegalArgumentException if height or bitrate are not supported. 153 * @throws IOException if output file cannot be created 154 * @throws IllegalStateException if a preview or an export is in progress or 155 * if no MediaItem has been added 156 * @throws CancellationException if export is canceled by calling 157 * {@link #cancelExport()} 158 * @throws UnsupportOperationException if multiple simultaneous export() 159 * are not allowed 160 */ 161 public void export(String filename, int height, int bitrate, ExportProgressListener listener) 162 throws IOException; 163 164 /** 165 * Cancel the running export operation. This method blocks until the 166 * export is canceled and the exported file (if any) is deleted. If the 167 * export completed by the time this method is invoked, the export file 168 * will be deleted. 169 * 170 * @param filename The filename which identifies the export operation to be 171 * canceled. 172 **/ 173 public void cancelExport(String filename); 174 175 /** 176 * Add a media item at the end of the storyboard. 177 * 178 * @param mediaItem The media item object to add 179 * @throws IllegalStateException if a preview or an export is in progress or 180 * if the media item id is not unique across all the media items 181 * added. 182 */ 183 public void addMediaItem(MediaItem mediaItem); 184 185 /** 186 * Insert a media item after the media item with the specified id. 187 * 188 * @param mediaItem The media item object to insert 189 * @param afterMediaItemId Insert the mediaItem after the media item 190 * identified by this id. If this parameter is null, the media 191 * item is inserted at the beginning of the timeline. 192 * 193 * @throws IllegalStateException if a preview or an export is in progress 194 * @throws IllegalArgumentException if media item with the specified id does 195 * not exist (null is a valid value) or if the media item id is 196 * not unique across all the media items added. 197 */ 198 public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId); 199 200 /** 201 * Move a media item after the media item with the specified id. 202 * 203 * Note: The project thumbnail is regenerated if the media item is or 204 * becomes the first media item in the storyboard timeline. 205 * 206 * @param mediaItemId The id of the media item to move 207 * @param afterMediaItemId Move the media item identified by mediaItemId after 208 * the media item identified by this parameter. If this parameter 209 * is null, the media item is moved at the beginning of the 210 * timeline. 211 * 212 * @throws IllegalStateException if a preview or an export is in progress 213 * @throws IllegalArgumentException if one of media item ids is invalid 214 * (null is a valid value) 215 */ 216 public void moveMediaItem(String mediaItemId, String afterMediaItemId); 217 218 /** 219 * Remove the media item with the specified id. If there are transitions 220 * before or after this media item, then this/these transition(s) are 221 * removed from the storyboard. If the extraction of the audio waveform is 222 * in progress, the extraction is canceled and the file is deleted. 223 * 224 * Effects and overlays associated with the media item will also be 225 * removed. 226 * 227 * Note: The project thumbnail is regenerated if the media item which 228 * is removed is the first media item in the storyboard or if the 229 * media item is the only one in the storyboard. If the 230 * media item is the only one in the storyboard, the project thumbnail 231 * will be set to a black frame and the aspect ratio will revert to the 232 * default aspect ratio, and this method is equivalent to 233 * removeAllMediaItems() in this case. 234 * 235 * @param mediaItemId The unique id of the media item to be removed 236 * 237 * @return The media item that was removed 238 * 239 * @throws IllegalStateException if a preview or an export is in progress 240 * @throws IllegalArgumentException if media item with the specified id 241 * does not exist 242 */ 243 public MediaItem removeMediaItem(String mediaItemId); 244 245 /** 246 * Remove all media items in the storyboard. All effects, overlays and all 247 * transitions are also removed. 248 * 249 * Note: The project thumbnail will be set to a black frame and the aspect 250 * ratio will revert to the default aspect ratio. 251 * 252 * @throws IllegalStateException if a preview or an export is in progress 253 */ 254 public void removeAllMediaItems(); 255 256 /** 257 * Get the list of media items in the order in which it they appear in the 258 * storyboard timeline. 259 * 260 * Note that if any media item source files are no longer 261 * accessible, this method will still provide the full list of media items. 262 * 263 * @return The list of media items. If no media item exist an empty list 264 * will be returned. 265 */ 266 public List<MediaItem> getAllMediaItems(); 267 268 /** 269 * Find the media item with the specified id 270 * 271 * @param mediaItemId The media item id 272 * 273 * @return The media item with the specified id (null if it does not exist) 274 */ 275 public MediaItem getMediaItem(String mediaItemId); 276 277 /** 278 * Add a transition between the media items specified by the transition. 279 * If a transition existed at the same position it is invalidated and then 280 * the transition is replaced. Note that the new transition video clip is 281 * not automatically generated by this method. The 282 * {@link Transition#generate()} method must be invoked to generate 283 * the transition video clip. 284 * 285 * Note that the TransitionAtEnd and TransitionAtStart are special kinds 286 * that can not be applied between two media items. 287 * 288 * A crossfade audio transition will be automatically applied regardless of 289 * the video transition. 290 * 291 * @param transition The transition to apply 292 * 293 * @throws IllegalStateException if a preview or an export is in progress 294 * @throws IllegalArgumentException if the transition duration is larger 295 * than the smallest duration of the two media item files or 296 * if the two media items specified in the transition are not 297 * adjacent 298 */ 299 public void addTransition(Transition transition); 300 301 /** 302 * Remove the transition with the specified id. 303 * 304 * @param transitionId The id of the transition to be removed 305 * 306 * @return The transition that was removed 307 * @throws IllegalStateException if a preview or an export is in progress 308 * @throws IllegalArgumentException if transition with the specified id does 309 * not exist 310 */ 311 public Transition removeTransition(String transitionId); 312 313 /** 314 * Get the list of transitions 315 * 316 * @return The list of transitions. If no transitions exist an empty list 317 * will be returned. 318 */ 319 public List<Transition> getAllTransitions(); 320 321 /** 322 * Find the transition with the specified transition id. 323 * 324 * @param transitionId The transition id 325 * 326 * @return The transition 327 */ 328 public Transition getTransition(String transitionId); 329 330 /** 331 * Add the specified AudioTrack to the storyboard. Note: Specific 332 * implementations may support a limited number of audio tracks (e.g. only 333 * one audio track) 334 * 335 * @param audioTrack The AudioTrack to add 336 * @throws UnsupportedOperationException if the implementation supports a 337 * limited number of audio tracks. 338 * @throws IllegalArgumentException if media item is not unique across all 339 * the audio tracks already added. 340 */ 341 public void addAudioTrack(AudioTrack audioTrack); 342 343 /** 344 * Insert an audio track after the audio track with the specified id. Use 345 * addAudioTrack to add an audio track at the end of the storyboard 346 * timeline. 347 * 348 * @param audioTrack The audio track object to insert 349 * @param afterAudioTrackId Insert the audio track after the audio track 350 * identified by this parameter. If this parameter is null the 351 * audio track is added at the beginning of the timeline. 352 * @throws IllegalStateException if a preview or an export is in progress 353 * @throws IllegalArgumentException if media item with the specified id does 354 * not exist (null is a valid value). if media item is not 355 * unique across all the audio tracks already added. 356 * @throws UnsupportedOperationException if the implementation supports a 357 * limited number of audio tracks 358 */ 359 public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId); 360 361 /** 362 * Move an AudioTrack after the AudioTrack with the specified id. 363 * 364 * @param audioTrackId The id of the AudioTrack to move 365 * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId 366 * after the AudioTrack identified by this parameter. If this 367 * parameter is null the audio track is added at the beginning of 368 * the timeline. 369 * @throws IllegalStateException if a preview or an export is in progress 370 * @throws IllegalArgumentException if one of media item ids is invalid 371 * (null is a valid value) 372 */ 373 public void moveAudioTrack(String audioTrackId, String afterAudioTrackId); 374 375 /** 376 * Remove the audio track with the specified id. If the extraction of the 377 * audio waveform is in progress, the extraction is canceled and the file is 378 * deleted. 379 * 380 * @param audioTrackId The id of the audio track to be removed 381 * 382 * @return The audio track that was removed 383 * @throws IllegalStateException if a preview or an export is in progress 384 */ 385 public AudioTrack removeAudioTrack(String audioTrackId); 386 387 /** 388 * Get the list of AudioTracks in order in which they appear in the storyboard. 389 * 390 * Note that if any AudioTrack source files are not accessible anymore, 391 * this method will still provide the full list of audio tracks. 392 * 393 * @return The list of AudioTracks. If no audio tracks exist an empty list 394 * will be returned. 395 */ 396 public List<AudioTrack> getAllAudioTracks(); 397 398 /** 399 * Find the AudioTrack with the specified id 400 * 401 * @param audioTrackId The AudioTrack id 402 * 403 * @return The AudioTrack with the specified id (null if it does not exist) 404 */ 405 public AudioTrack getAudioTrack(String audioTrackId); 406 407 /** 408 * Set the aspect ratio used in the preview and the export movie. 409 * 410 * The default aspect ratio is ASPECTRATIO_16_9 (16:9). 411 * 412 * @param aspectRatio to apply. If aspectRatio is the same as the current 413 * aspect ratio, then this function just returns. The supported 414 * aspect ratio are defined in the MediaProperties class for 415 * example: ASPECTRATIO_16_9 416 * 417 * @throws IllegalStateException if a preview or an export is in progress 418 * @throws IllegalArgumentException if aspect ratio is not supported 419 */ 420 public void setAspectRatio(int aspectRatio); 421 422 /** 423 * Get current aspect ratio. 424 * 425 * @return The aspect ratio as described in MediaProperties 426 */ 427 public int getAspectRatio(); 428 429 /** 430 * Get the preview (and output movie) duration. 431 * 432 * @return The duration of the preview (and output movie) 433 */ 434 public long getDuration(); 435 436 /** 437 * Render a frame according to the preview aspect ratio and activating all 438 * storyboard items relative to the specified time. 439 * 440 * @param surfaceHolder SurfaceHolder used by the application 441 * @param timeMs time corresponding to the frame to display 442 * 443 * @return The accurate time stamp of the frame that is rendered 444 * . 445 * @throws IllegalStateException if a preview or an export is already 446 * in progress 447 * @throws IllegalArgumentException if time is negative or beyond the 448 * preview duration 449 */ 450 public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs); 451 452 /** 453 * This method must be called after the aspect ratio of the project changes 454 * and before startPreview is called. Note that this method may block for 455 * an extensive period of time. 456 */ 457 public void generatePreview(); 458 459 /** 460 * Start the preview of all the storyboard items applied on all MediaItems 461 * This method does not block (does not wait for the preview to complete). 462 * The PreviewProgressListener allows to track the progress at the time 463 * interval determined by the callbackAfterFrameCount parameter. The 464 * SurfaceHolder has to be created and ready for use before calling this 465 * method. The method is a no-op if there are no MediaItems in the 466 * storyboard. 467 * 468 * @param surfaceHolder SurfaceHolder where the preview is rendered. 469 * @param fromMs The time (relative to the timeline) at which the preview 470 * will start 471 * @param toMs The time (relative to the timeline) at which the preview will 472 * stop. Use -1 to play to the end of the timeline 473 * @param loop true if the preview should be looped once it reaches the end 474 * @param callbackAfterFrameCount The listener interface should be invoked 475 * after the number of frames specified by this parameter. 476 * @param listener The listener which will be notified of the preview 477 * progress 478 * @throws IllegalArgumentException if fromMs is beyond the preview duration 479 * @throws IllegalStateException if a preview or an export is already in 480 * progress 481 */ 482 public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs, boolean loop, 483 int callbackAfterFrameCount, PreviewProgressListener listener); 484 485 /** 486 * Stop the current preview. This method blocks until ongoing preview is 487 * stopped. Ignored if there is no preview running. 488 * 489 * @return The accurate current time when stop is effective expressed in 490 * milliseconds 491 */ 492 public long stopPreview(); 493} 494