Video clipper #115
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces an Android application for automated video highlight generation and intelligent editing suggestions using Vertex AI for Firebase and Firebase Cloud Storage. The feedback highlights several critical compilation errors and logic issues, including the use of non-existent Media3 APIs (MetadataRetriever and EditedMediaItemSequence.withAudioAndVideoFrom), conflicting imports for PlayPauseButton, and a type mismatch in Long.coerceIn. Additionally, improvements are suggested to handle background thread operations for metadata retrieval, prevent stale state on screen re-initialization, validate user intent input, and safely abort processing if any video upload fails.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| class VideoAnalysisViewModel(application: Application) : AndroidViewModel(application) { | ||
| private val _uiState = MutableStateFlow(VideoAnalysisUiState()) | ||
| val uiState: StateFlow<VideoAnalysisUiState> = _uiState.asStateFlow() | ||
|
|
||
| fun initialize(jsonResponse: String, uriPairs: List<Pair<String, Uri>>) { | ||
| if (_uiState.value.videos.isNotEmpty()) return // Already initialized |
There was a problem hiding this comment.
Using _uiState.value.videos.isNotEmpty() as a guard prevents the screen from updating if the user goes back, edits again, and comes back with a new response (since the ViewModel might be reused and state is already populated). We can track the last processed jsonResponse in the ViewModel to safely skip initialization only when the input is identical, while correctly resetting state for new inputs.
| class VideoAnalysisViewModel(application: Application) : AndroidViewModel(application) { | |
| private val _uiState = MutableStateFlow(VideoAnalysisUiState()) | |
| val uiState: StateFlow<VideoAnalysisUiState> = _uiState.asStateFlow() | |
| fun initialize(jsonResponse: String, uriPairs: List<Pair<String, Uri>>) { | |
| if (_uiState.value.videos.isNotEmpty()) return // Already initialized | |
| class VideoAnalysisViewModel(application: Application) : AndroidViewModel(application) { | |
| private val _uiState = MutableStateFlow(VideoAnalysisUiState()) | |
| val uiState: StateFlow<VideoAnalysisUiState> = _uiState.asStateFlow() | |
| private var lastJsonResponse: String? = null | |
| fun initialize(jsonResponse: String, uriPairs: List<Pair<String, Uri>>) { | |
| if (jsonResponse == lastJsonResponse) return // Already initialized for this response | |
| lastJsonResponse = jsonResponse |
There was a problem hiding this comment.
Fine as-is for a demo and can be deferred for later improvement if needed
| .fillMaxWidth() | ||
| .height(56.dp) | ||
| .align(Alignment.BottomCenter), | ||
| enabled = uiState.selectedVideoUris.isNotEmpty() && !uiState.isLoading |
There was a problem hiding this comment.
We should require the user to enter a non-blank editing intent before enabling the 'Edit with Gemini' button. This prevents sending empty prompts to the AI model.
| enabled = uiState.selectedVideoUris.isNotEmpty() && !uiState.isLoading | |
| enabled = uiState.selectedVideoUris.isNotEmpty() && uiState.intentText.isNotBlank() && !uiState.isLoading |
There was a problem hiding this comment.
Fine as-is for a demo and can be deferred for later improvement if needed
| if (newUriPairs.isEmpty()) { | ||
| _uiState.update { | ||
| it.copy( | ||
| isLoading = false, | ||
| errorMessage = "No files were uploaded successfully. Cannot proceed." | ||
| ) | ||
| } | ||
| return@launch | ||
| } |
There was a problem hiding this comment.
If some uploads fail but others succeed, the app currently proceeds to call Gemini with a partial list of videos. This can lead to unexpected behavior or broken states. It is safer to abort the process and show an error if any of the selected videos fail to upload.
| if (newUriPairs.isEmpty()) { | |
| _uiState.update { | |
| it.copy( | |
| isLoading = false, | |
| errorMessage = "No files were uploaded successfully. Cannot proceed." | |
| ) | |
| } | |
| return@launch | |
| } | |
| if (newUriPairs.size < currentState.selectedVideoUris.size) { | |
| _uiState.update { | |
| it.copy( | |
| isLoading = false, | |
| errorMessage = "One or more videos failed to upload. Cannot proceed." | |
| ) | |
| } | |
| return@launch | |
| } |
There was a problem hiding this comment.
Fine as-is for a demo and can be deferred for later improvement if needed
An Android application demonstrating automated video highlight generation and intelligent cinematic editing suggestion using Vertex AI for Firebase and Firebase Cloud Storage.
Users can select multiple videos, specify editing goals in natural language (e.g., "create a fast-paced 15-second action reel"), upload them to Cloud Storage, and let Gemini analyze the content to recommend and preview video trims and edits.