Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ group 'me.anharu.video_editor'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.5.10'
repositories {
google()
// maven { url 'https://jitpack.io' }
mavenCentral()
jcenter()
}

Expand All @@ -17,7 +19,10 @@ buildscript {
rootProject.allprojects {
repositories {
google()
// maven { url 'https://jitpack.io' }
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
}
}

Expand All @@ -41,5 +46,7 @@ android {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.github.MasayukiSuda:Mp4Composer-android:v0.3.9'
implementation 'com.github.umuieme:Mp4Composer-android:buffer_size_fix-SNAPSHOT'
implementation 'com.android.support:support-v4:28.0.0'

}
51 changes: 51 additions & 0 deletions android/src/main/kotlin/me/anharu/video_editor/SpeedChanger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package me.anharu.video_editor


import android.app.Activity
import com.daasuu.mp4compose.composer.Mp4Composer
import io.flutter.plugin.common.MethodChannel.Result

class SpeedChanger(inputVideo: String, outputVideo: String, val result: Result, val activity: Activity) {
var composer: Mp4Composer = Mp4Composer(inputVideo, outputVideo)

fun speed(speed: Float) {
print("speed ==== $speed")
try {
composer.timeScale(speed)
.listener(object : Mp4Composer.Listener {
override fun onProgress(progress: Double) {

}

override fun onCurrentWrittenVideoTime(timeUs: Long) {
}

override fun onCompleted() {
activity.runOnUiThread(Runnable {
result.success(null)
})
}

override fun onCanceled() {
activity.runOnUiThread(Runnable {
result.error("user_cancelled", "Cancelled by user", null)
})
}

override fun onFailed(exception: Exception) {
exception.printStackTrace()
activity.runOnUiThread(Runnable {
result.error("video_trim_failed", exception.message, null)
})
}

}).start();
} catch (e: Exception) {
print("Error ====== ${e.message}")
e.printStackTrace()
activity.runOnUiThread(Runnable {
result.error("video_trim_failed", e.message, null)
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package me.anharu.video_editor

import android.Manifest
import android.app.Activity
import android.util.Log
import androidx.annotation.NonNull
import androidx.core.app.ActivityCompat
import com.daasuu.mp4compose.composer.Mp4Composer
Expand Down Expand Up @@ -93,7 +94,22 @@ public class VideoEditorPlugin : FlutterPlugin, MethodCallHandler, PluginRegistr
val endTime: Long = call.argument<Int>("endTime")?.toLong() ?: -1
VideoTrimmer(srcFilePath, destFilePath, result, getActivity).trimVideo(startTime, endTime)
}
"speed_change" -> {
val getActivity = activity ?: return
val srcFilePath: String = call.argument("srcFilePath") ?: run {
result.error("src_file_path_not_found", "the src file path is not found.", null)
return
}
val destFilePath: String = call.argument("destFilePath") ?: run {
result.error("dest_file_path_not_found", "the dest file path is not found.", null)
return
}
val speed: Float = call.argument<Double>("speed")?.toFloat() ?: 0F
Log.e("Videoeditor","===>$speed");
SpeedChanger(srcFilePath, destFilePath, result, getActivity).speed(speed)
}
else -> {
print("===>sxxxxxxxx");
result.notImplemented()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class VideoGeneratorService(
override fun onProgress(progress: Double) {
println("onProgress = " + progress)
}
override fun onCurrentWrittenVideoTime(timeUs: Long) {

}

override fun onCompleted() {
activity.runOnUiThread(Runnable {
Expand Down
64 changes: 38 additions & 26 deletions android/src/main/kotlin/me/anharu/video_editor/VideoTrimmer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,43 @@ class VideoTrimmer(inputVideo: String, outputVideo: String, val result: Result,
var composer: Mp4Composer = Mp4Composer(inputVideo, outputVideo)

fun trimVideo(startTime: Long = 0, endTime: Long = -1) {
composer.trim(startTime, endTime)
.listener(object : Mp4Composer.Listener {
override fun onProgress(progress: Double) {

}

override fun onCompleted() {
activity.runOnUiThread(Runnable {
result.success(null)
})
}

override fun onCanceled() {
activity.runOnUiThread(Runnable {
result.error("user_cancelled", "Cancelled by user", null)
})
}

override fun onFailed(exception: Exception?) {
exception?.printStackTrace()
activity.runOnUiThread(Runnable {
result.error("video_trim_failed", exception?.localizedMessage, exception?.stackTrace)
})
}

}).start();
try {
composer.trim(startTime, endTime)
.listener(object : Mp4Composer.Listener {
override fun onProgress(progress: Double) {

}

override fun onCurrentWrittenVideoTime(timeUs: Long) {

}

override fun onCompleted() {
activity.runOnUiThread(Runnable {
result.success(null)
})
}

override fun onCanceled() {
activity.runOnUiThread(Runnable {
result.error("user_cancelled", "Cancelled by user", null)
})
}

override fun onFailed(exception: Exception) {
exception.printStackTrace()
activity.runOnUiThread(Runnable {
result.error("video_trim_failed", exception.message, exception.stackTrace)
})
}

}).start();
} catch (e: Exception) {
print("Error ====== ${e.message}")
e.printStackTrace()
activity.runOnUiThread(Runnable {
result.error("video_trim_failed", e.message, e.stackTrace)
})
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,66 @@
package me.anharu.video_editor.filter

import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.*
import com.daasuu.mp4compose.filter.GlOverlayFilter
import me.anharu.video_editor.ImageOverlay
import android.graphics.Bitmap

import android.graphics.BitmapFactory


import java.io.ByteArrayOutputStream

class GlImageOverlayFilter(imageOverlay: ImageOverlay) : GlOverlayFilter() {
private val imageOverlay: ImageOverlay = imageOverlay;

protected override fun drawCanvas(canvas: Canvas) {
canvas.drawBitmap(BitmapFactory.decodeByteArray(imageOverlay.bitmap, 0, imageOverlay.bitmap.size), imageOverlay.x.toFloat(), imageOverlay.y.toFloat(), null);
var b = BitmapFactory.decodeByteArray (imageOverlay.bitmap, 0, imageOverlay.bitmap.size)
var bitmap= getResizedBitmap(b, b.height/2,b.width/2)
// Bitmap.createScaledBitmap(b, b.width/2, b.height/2, true);
canvas.drawBitmap(b, imageOverlay.x.toFloat(), imageOverlay.y.toFloat(), null);
}
fun scaleBitmaps(bitmap: Bitmap, wantedWidth: Int, wantedHeight: Int): Bitmap {
val output = Bitmap.createBitmap(wantedWidth, wantedHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val m = Matrix()
m.setScale(wantedWidth.toFloat() / bitmap.width, wantedHeight.toFloat() / bitmap.height)
canvas.drawBitmap(bitmap,m, Paint(Paint.FILTER_BITMAP_FLAG))
return output
}

fun getResizedBitmap(bm: Bitmap, newHeight: Int, newWidth: Int): Bitmap {
val width = bm.width
val height = bm.height
val scaleWidth = newWidth.toFloat() / width
val scaleHeight = newHeight.toFloat() / height
// create a matrix for the manipulation
val matrix = Matrix()
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight)

// recreate the new Bitmap
var dd= Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true)
var outputStream = ByteArrayOutputStream()
dd.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
return dd;

}
fun scaleBitmap(bitmap: Bitmap, wantedWidth: Int, wantedHeight: Int): Bitmap {
val originalWidth = bitmap.width.toFloat()
val originalHeight = bitmap.height.toFloat()
val output = Bitmap.createBitmap(wantedWidth, wantedHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val m = Matrix()
val scalex = wantedWidth / originalWidth
val scaley = wantedHeight / originalHeight
// val xTranslation = 0.0f
// val yTranslation = (wantedHeight - originalHeight * scaley) / 2.0f
// m.postTranslate(xTranslation, yTranslation)
m.preScale(scalex, scaley)
// m.setScale((float) wantedWidth / bitmap.getWidth(), (float) wantedHeight / bitmap.getHeight());
val paint = Paint()
paint.isFilterBitmap = true
canvas.drawBitmap(bitmap, m, paint)
return output
}
}
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.4.32'
repositories {
google()
jcenter()
Expand Down
2 changes: 1 addition & 1 deletion example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https://services.gradle.org/distributions/gradle-6.4.1-all.zip
Binary file added example/assets/teest1.mp4
Binary file not shown.
Binary file added example/assets/test.mp4
Binary file not shown.
33 changes: 33 additions & 0 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
PODS:
- camera (0.0.1):
- Flutter
- Flutter (1.0.0)
- gallery_saver (0.0.1):
- Flutter
- image_picker (0.0.1):
- Flutter
- libwebp (1.2.0):
- libwebp/demux (= 1.2.0)
- libwebp/mux (= 1.2.0)
- libwebp/webp (= 1.2.0)
- libwebp/demux (1.2.0):
- libwebp/webp
- libwebp/mux (1.2.0):
- libwebp/demux
- libwebp/webp (1.2.0)
- path_provider (0.0.1):
- Flutter
- tapioca (0.0.1):
- Flutter
- video_compress (0.3.0):
- Flutter
- video_player (0.0.1):
- Flutter
- video_thumbnail (0.0.1):
- Flutter
- libwebp

DEPENDENCIES:
- camera (from `.symlinks/plugins/camera/ios`)
- Flutter (from `Flutter`)
- gallery_saver (from `.symlinks/plugins/gallery_saver/ios`)
- image_picker (from `.symlinks/plugins/image_picker/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- tapioca (from `.symlinks/plugins/tapioca/ios`)
- video_compress (from `.symlinks/plugins/video_compress/ios`)
- video_player (from `.symlinks/plugins/video_player/ios`)
- video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)

SPEC REPOS:
trunk:
- libwebp

EXTERNAL SOURCES:
camera:
:path: ".symlinks/plugins/camera/ios"
Flutter:
:path: Flutter
gallery_saver:
Expand All @@ -30,16 +55,24 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider/ios"
tapioca:
:path: ".symlinks/plugins/tapioca/ios"
video_compress:
:path: ".symlinks/plugins/video_compress/ios"
video_player:
:path: ".symlinks/plugins/video_player/ios"
video_thumbnail:
:path: ".symlinks/plugins/video_thumbnail/ios"

SPEC CHECKSUMS:
camera: 3164201dc344383e62282964016528c4f5a9ad50
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
gallery_saver: 9fc173c9f4fcc48af53b2a9ebea1b643255be542
image_picker: 50e7c7ff960e5f58faa4d1f4af84a771c671bc4a
libwebp: e90b9c01d99205d03b6bb8f2c8c415e5a4ef66f0
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
tapioca: 59e9fc89671d49e2cefe6cd59c3efe678e589e89
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1

PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c

Expand Down
Loading