Skip to content

Video clipper #115

Merged
SigmanZero merged 4 commits into
android:mainfrom
droid-girl:video-clipper
Jun 23, 2026
Merged

Video clipper #115
SigmanZero merged 4 commits into
android:mainfrom
droid-girl:video-clipper

Conversation

@droid-girl

Copy link
Copy Markdown
Contributor

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +38 to +43
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
enabled = uiState.selectedVideoUris.isNotEmpty() && !uiState.isLoading
enabled = uiState.selectedVideoUris.isNotEmpty() && uiState.intentText.isNotBlank() && !uiState.isLoading

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine as-is for a demo and can be deferred for later improvement if needed

Comment on lines +82 to +90
if (newUriPairs.isEmpty()) {
_uiState.update {
it.copy(
isLoading = false,
errorMessage = "No files were uploaded successfully. Cannot proceed."
)
}
return@launch
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine as-is for a demo and can be deferred for later improvement if needed

@SigmanZero SigmanZero merged commit 1313ce3 into android:main Jun 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants