Fix bitrate value used for video transcoding (#5183)
* Fix bitrate value used for video transcoding: It should be 1000 times what it is now. The video size estimation was wrong since the retrieved duration value was in milliseconds, not seconds. * Use `Duration` as the result type for `getDuration`
This commit is contained in:
parent
aac9642159
commit
5feb7a99a9
5 changed files with 15 additions and 8 deletions
|
|
@ -101,8 +101,9 @@ class DefaultMediaOptimizationSelectorPresenter @AssistedInject constructor(
|
||||||
|
|
||||||
val sizeEstimations = VideoCompressionPreset.entries
|
val sizeEstimations = VideoCompressionPreset.entries
|
||||||
.map { preset ->
|
.map { preset ->
|
||||||
val bitRate = preset.compressorHelper().calculateOptimalBitrate(videoDimensions, 30)
|
val bitRateAsBytes = preset.compressorHelper().calculateOptimalBitrate(videoDimensions, 30) / 8f
|
||||||
val calculatedSize = (bitRate * duration / 8 * 1.1).roundToLong() // Adding 10% overhead for safety
|
val durationInSeconds = duration.inWholeSeconds.toFloat()
|
||||||
|
val calculatedSize = (bitRateAsBytes * durationInSeconds * 1.1f).roundToLong() // Adding 10% overhead for safety
|
||||||
VideoUploadEstimation(
|
VideoUploadEstimation(
|
||||||
preset = preset,
|
preset = preset,
|
||||||
sizeInBytes = calculatedSize,
|
sizeInBytes = calculatedSize,
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,12 @@ import dagger.assisted.AssistedInject
|
||||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
interface VideoMetadataExtractor : AutoCloseable {
|
interface VideoMetadataExtractor : AutoCloseable {
|
||||||
fun getSize(): Result<Size>
|
fun getSize(): Result<Size>
|
||||||
fun getDuration(): Result<Long>
|
fun getDuration(): Result<Duration>
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(uri: Uri): VideoMetadataExtractor
|
fun create(uri: Uri): VideoMetadataExtractor
|
||||||
}
|
}
|
||||||
|
|
@ -57,9 +59,10 @@ class DefaultVideoMetadataExtractor @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDuration(): Result<Long> = runCatchingExceptions {
|
override fun getDuration(): Result<Duration> = runCatchingExceptions {
|
||||||
mediaMetadataRetriever.value.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
|
mediaMetadataRetriever.value.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
|
||||||
?.takeIf { it > 0L }
|
?.takeIf { it > 0L }
|
||||||
|
?.milliseconds
|
||||||
?: error("Could not retrieve video duration from metadata")
|
?: error("Could not retrieve video duration from metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class DefaultMediaOptimizationSelectorPresenterTest {
|
class DefaultMediaOptimizationSelectorPresenterTest {
|
||||||
|
|
@ -158,7 +159,7 @@ class DefaultMediaOptimizationSelectorPresenterTest {
|
||||||
mediaExtractorFactory = FakeVideoMetadataExtractorFactory(
|
mediaExtractorFactory = FakeVideoMetadataExtractorFactory(
|
||||||
FakeVideoMetadataExtractor(
|
FakeVideoMetadataExtractor(
|
||||||
sizeResult = Result.success(Size(10_000, 10_000)),
|
sizeResult = Result.success(Size(10_000, 10_000)),
|
||||||
duration = Result.success(600L)
|
duration = Result.success(10.minutes)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,16 @@ package io.element.android.features.messages.test.attachments.video
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import io.element.android.features.messages.impl.attachments.video.VideoMetadataExtractor
|
import io.element.android.features.messages.impl.attachments.video.VideoMetadataExtractor
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
class FakeVideoMetadataExtractor(
|
class FakeVideoMetadataExtractor(
|
||||||
private val sizeResult: Result<Size> = Result.success(Size(1, 1)),
|
private val sizeResult: Result<Size> = Result.success(Size(1, 1)),
|
||||||
private val duration: Result<Long> = Result.success(1L),
|
private val duration: Result<Duration> = Result.success(1.milliseconds),
|
||||||
) : VideoMetadataExtractor {
|
) : VideoMetadataExtractor {
|
||||||
override fun getSize(): Result<Size> = sizeResult
|
override fun getSize(): Result<Size> = sizeResult
|
||||||
|
|
||||||
override fun getDuration(): Result<Long> = duration
|
override fun getDuration(): Result<Duration> = duration
|
||||||
|
|
||||||
override fun close() = Unit
|
override fun close() = Unit
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class VideoCompressorHelper(
|
||||||
val pixelsPerFrame = outputSize.width * outputSize.height
|
val pixelsPerFrame = outputSize.width * outputSize.height
|
||||||
// Apparently, 0.1 bits per pixel is a sweet spot for video compression
|
// Apparently, 0.1 bits per pixel is a sweet spot for video compression
|
||||||
val bitsPerPixel = 0.1f
|
val bitsPerPixel = 0.1f
|
||||||
return (pixelsPerFrame * bitsPerPixel * frameRate).toLong() / 1000
|
return (pixelsPerFrame * bitsPerPixel * frameRate).toLong()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue