如何模糊视频视图?

问题描述 投票:0回答:2

我想模糊正在播放原始文件夹中视频的视频视图。

可以使用渲染脚本或 Blurry 等库来模糊图像视图或包含可绘制背景的布局。但是如何对视频进行模糊处理呢?我尝试了将视频的 uri 路径转换为位图、视频转换为缩略图等方法,但没有成功。

这是我的代码。

package com.example.myapplication

import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.MediaController
import android.widget.VideoView

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val videoView = findViewById(R.id.videoView) as VideoView
    val mediaController = MediaController(this)
    mediaController.setAnchorView(videoView)
    val uri = Uri.parse("android.resource://" + packageName + "/" + R.raw.samplevideo)
    videoView.setMediaController(mediaController)
    videoView.setVideoURI(uri)
    videoView.requestFocus()
    videoView.start()

    var runnable = Runnable {


        var resultBmp = BlurBuilder.blur(this, BitmapFactory.decodeResource(resources, R.raw.samplevideo))
        var drawable = BitmapDrawable(resources, resultBmp)
        videoView.background = drawable

    }

    videoView.post(runnable)
}

}

activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<RelativeLayout
        android:id="@+id/relativeLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">


    <VideoView
            android:id="@+id/videoView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

</RelativeLayout>

BlurBuilder.kt

package com.example.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;

object BlurBuilder {

private val BITMAP_SCALE = 0.6f
private val BLUR_RADIUS = 15f

fun blur(context: Context, image: Bitmap): Bitmap {
    val width = Math.round(image.width * BITMAP_SCALE)
    val height = Math.round(image.height * BITMAP_SCALE)

    val inputBitmap = Bitmap.createScaledBitmap(image, width, height, false)
    val outputBitmap = Bitmap.createBitmap(inputBitmap)

    val rs = RenderScript.create(context)

    val intrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
    val tmpIn = Allocation.createFromBitmap(rs, inputBitmap)
    val tmpOut = Allocation.createFromBitmap(rs, outputBitmap)

    intrinsicBlur.setRadius(BLUR_RADIUS)
    intrinsicBlur.setInput(tmpIn)
    intrinsicBlur.forEach(tmpOut)
    tmpOut.copyTo(outputBitmap)

    return outputBitmap
}

}

请帮助我模糊视频视图或包含视频视图的相对布局。

android
2个回答
0
投票

我有类似的要求,并得出结论,目前模糊效果只能在 Android 的静态图像上实现。与 iOS 相反,iOS 上有一个实际的模糊选项可以用于任何东西之上。

解决方法

因此,我们仅在视频暂停时添加模糊效果。

检索要使用的视频帧

从视频中获取单帧可以通过这个SO问题的答案来完成如何在Exoplayer中连续获取特定位置的视频帧

注意需要在IO线程上完成!下面的代码摘录已经使用

renderscript.Toolkit
应用了模糊效果。

    private var thumbnail: Bitmap? = null
    private var thumbnailBlur: Bitmap? = null
    private val retriever = MediaMetadataRetriever()

    private fun captureEndScreen(uri: String) {
        // manually retrieve thumbnail form video source in background to be used for end screen and blur
        (context as? LifecycleOwner)?.lifecycleScope?.launch(Dispatchers.IO) {
            retriever.setDataSource(uri)
            thumbnail = retriever.getFrameAtTime(100)
            thumbnailBlur = thumbnail?.copy(Bitmap.Config.ARGB_8888, false) // needs ARGB_8888 for blur effect
            withContext(Dispatchers.Main) {
                thumbnailBlur?.let {
                    // applies blur effect using Toolkit
                    view.setImageBitmap(Toolkit.blur(it, BLUR_RADIUS))
            }
        }
    }

对单帧应用模糊

对于模糊效果,出于兼容性原因,您可以使用上面代码中的

Toolkit
或下面的解决方法。

这里有一个关于如何在静态图像上创建模糊的示例项目:https://github.com/hanscappelle/demo_android_imageview_scaletype来自这个SO问题Android模糊视图(模糊视图后面的背景)

/**
 * source: https://developer.android.com/guide/topics/renderscript/migrate#image_blur_on_android_12_into_a_view
 */
private fun applyBlur(view: View, radius: Float) {
    val blurRenderEffect = RenderEffect.createBlurEffect(
        radius, radius,
        Shader.TileMode.MIRROR
    )
    view.setRenderEffect(blurRenderEffect)
}

0
投票

我们遇到了同样的问题,并通过解决方法解决了它。

我们首先尝试使用 OpenGL 着色器,如本答案中所述 https://stackoverflow.com/a/38125734/11253860,它使用 VidEffects 库 (https://github.com/krazykira/VidEffects) 。但我们找不到质量和性能之间的最佳平衡点。我们的另一个缺点是 OpenGL 相关代码对于普通 Android 开发人员来说很难维护。

因为我们的视频很短,所以我们最终将其转换为 GIF,可以简单地使用 Android 12+ 的原生 Blur() 函数对其进行模糊处理。

import coil3.compose.AsyncImage

AsyncImage(
        modifier = Modifier.fillMaxWidth().blur(20.dp),
        model = "https://example.gif",
        contentScale = ContentScale.FillWidth,
        contentDescription = null,
)

对于 12 以下的 Android 版本,我们决定使用 Cloudy 库 (https://github.com/skydoves/Cloudy)。这里的缺点是 GIF 停止播放,你只能看到模糊的静态第一帧。对于我们的用例,并且因为我们的大多数用户都使用 Android 12+,所以这对我们来说是一个足够好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.