I am trying to build a project that allows users to enter a video(via their gallery or recording) and apply filters to that video via GPUVideo library but I can't manage to apply filters to the videos it doesn't change anything about it. Should I use something else then URI for playing the video or change the library that I am using? Here is my code:
FilterFragment
class FilterFragment : Fragment() {
private lateinit var binding: FragmentFilterBinding
private val viewModel: FilterViewModel by viewModels()
private val TAG = "FilterFragment"
//Fields
private lateinit var filteredVid: VideoView
private lateinit var saveBtn: FloatingActionButton
private lateinit var filterOptions: ChipGroup
private lateinit var sourceVideoUri: Uri
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentFilterBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeFields()
}
private fun initializeFields() {
filteredVid = binding.videoView
saveBtn = binding.floatingActionButton
filterOptions = binding.chipGroup
// Get the URI of the video from the arguments
sourceVideoUri = arguments?.getString("videoUri")!!.toUri()
// Creating temp file to reference path
val contentResolver = requireContext().contentResolver
val inputStream = contentResolver.openInputStream(sourceVideoUri)
val tempFile = createTempFile("temp", null, requireContext().cacheDir)
tempFile.outputStream().use { outputStream ->
inputStream?.copyTo(outputStream)
}
applyFilter(GlBilateralFilter(), tempFile.path)
// Set the video URI as the data source for the VideoView
Log.d(TAG,"Before start")
filteredVid.setVideoURI(sourceVideoUri)
// Start playing the video
filteredVid.start()
Log.d(TAG,"After start")
}
private fun applyFilter(appliedFilter: GlFilter,filePath : String) {
lifecycleScope.launch {
GPUMp4Composer(filePath, filePath)
.rotation(Rotation.ROTATION_90)
.size(540, 960)
.fillMode(FillMode.PRESERVE_ASPECT_FIT)
.filter(appliedFilter)
.listener(object : GPUMp4Composer.Listener {
override fun onProgress(progress: Double) {
Log.d(TAG, "onProgress = $progress")
}
override fun onCompleted() {
Log.d(TAG, "onCompleted()")
// Toast.makeText(context, "codec complete path =$filePath.toString()", Toast.LENGTH_SHORT).show()
}
override fun onCanceled() {
Log.d(TAG, "onCanceled")
}
override fun onFailed(exception: Exception?) {
Log.e(TAG, "onFailed()", exception)
}
})
.start()
}
}
}
Input Fragment
class InputFragment : Fragment() {
//Binding
private lateinit var binding: FragmentInputBinding
//Fields
private lateinit var recordBtn: Button
private lateinit var chooseBtn: Button
private lateinit var filterBtn: Button
private lateinit var previewVid: VideoView
private lateinit var viewModel: InputViewModel
private var videoInputUri: Uri? = null
private val videoChooser =
registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
uri?.let {
videoInputUri = it
prepareVideoInput(it)
previewVid.visibility = View.VISIBLE
}
}
private val videoRecorder =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.data?.let { uri ->
videoInputUri = uri
viewModel.selectVideoUri(uri)
}
previewVid.visibility = View.VISIBLE
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentInputBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initializeFields()
}
private fun initializeFields() {
viewModel = ViewModelProvider(this)[InputViewModel::class.java]
chooseBtn = binding.chooseVideoBtn
recordBtn = binding.recordVideoBtn
filterBtn = binding.animateBtn
previewVid = binding.videoView
chooseBtn.setOnClickListener {
launchVideoChooser()
}
recordBtn.setOnClickListener {
launchVideoRecorder()
}
filterBtn.setOnClickListener {
if (previewVid.isVisible) {
val videoUri = videoInputUri.toString()
val bundle = bundleOf("videoUri" to videoUri)
binding.root.findNavController().navigate(R.id.action_inputFragment_to_filterFragment,bundle)
}
else
Toast.makeText(requireActivity(),"Enter a Video!",Toast.LENGTH_SHORT).show()
}
viewModel.selectedVideoUri.observe(viewLifecycleOwner) { uri ->
videoInputUri = uri
if (videoInputUri != null) {
prepareVideoInput(videoInputUri!!)
}
}
}
private fun launchVideoChooser() {
videoChooser.launch("video/*")
}
private fun launchVideoRecorder() {
val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
videoRecorder.launch(intent)
}
private fun prepareVideoInput(videoUri: Uri) {
previewVid.setVideoURI(videoUri)
previewVid.start()
}
companion object {
private const val REQUEST_VIDEO_RECORDER = 2
}
}