You need to enable JavaScript to run this app.
导航
剪同款接入
最近更新时间:2025.05.13 16:04:03首次发布时间:2025.05.13 16:04:03
我的收藏
有用
有用
无用
无用
前提条件
  • 支持Android 5.0或以上的设备,暂不支持模拟器调试

  • 确保申请到有效的License

  • 确保申请到Maven仓库的账号密码:获取方法请联系和您对接的技术支持经理

相关SDK介绍

版本号:5.0.1-rc.5-v130

NameCoordinate说明
CutSame SDKcom.volcengine.ck.cutsame:CK-CutSameIF剪同款模版消费SDK,负责模版的重演,更新,合成能力。
//build.gradle
dependencies {
    implementation "com.volcengine.ck.cutsame:CK-CutSameIF:5.0.1-rc.5-v130"
}
接口调用流程

alt

获取模版列表

获取的数据主要为模版信息(模版标题,模版预览视频等)。主要两个作用,第一提供页面展示信息数据,第二构造后续模版重演流程需要的数据TemplateItem

获取模版槽位信息

后续素材选择模版重演播放均需要模版槽位信息,模版槽位信息包括素材路径,素材类型,materialId(模版的槽位id)等信息,详细见获取模版媒体素材部分MediaItem的定义
获取模板槽位信息方式:通过CutSameSource的prepareSource()方法获取到List <MediaItem>

填充模版槽位信息

主要填充MediaItem中的相关字段,如source,mediaSrcPath,type,oriDuration。字段含义详情见获取模版媒体素材部分MediaItem的定义。主要关注需要业务赋值部分

素材合成处理

经过填充模版槽位信息步骤后,需要调用CutSameSource.composeSource()接口进行素材合成处理,主要进行以下处理:

  • 对素材进行压缩处理,减少素材分辨率,提高重演效率。

  • 根据模版制作规则,按需对素材进行倒放处理。

模版重演播放

经过上述步骤后,将List传入CutSamePlayer.preparePlay()方法中,设置PlayerStateListener,监听播放变化。当PLAYER_STATE_PREPARED时,即可调用start()接口进行重演播放。

接口介绍

初始化&模板准备

配置鉴权初始化

功能描述

设置鉴权配置,SDK鉴权相关的配置

代码示例

  • 将离线鉴权文件放置到宿主工程/app/src/main/assets/License/目录下

  • 拷贝离线鉴权文件到App私有目录下

// 根据文件名,拷贝离线鉴权文件到App私有目录下
val licenseFileName = "com.volcengine.effectone.licbag"
val licenseFile = File(EOUtils.pathUtil.internalLicense(), licenseFileName)
if (!licenseFile.exists()) {
    EOUtils.fileUtil.copyAssetFile("license/${licenseFileName}", licenseFile.absolutePath)
}
  • 初始化鉴权
val authConfig = EOAuthConfig()
authConfig.offlineLicensePath = "鉴权文件本地路径"
val result = EOAuthorization.makeAuthWithConfig(authConfig)
if (result.resCode != EOAuthErrCode.EO_AUTH_SUCCESS) {
    //鉴权失败
} else {
    //鉴权成功
}

//cutSameLicensePath即有可用的剪同款授权文件
val cutSameLicensePath = EOAuthorizationInternal.getCutSameLicensePath()

SDK初始化

功能描述

鉴权初始化成功以后,初始化剪同款SDK相关的配置

代码示例

EffectOneConfigList.configure(CutSameUIConfig()) {
    //剪同款模板内置或者下发可以通过在这配置OnlineResourceLoader或OfflineResourceLoader
        it.resourceLoader = OnlineResourceLoader.instance
}
CutSameInit.init()

获取模板列表

功能描述

获取剪同款的模板列表,用于展示和构造TemplateItem用于模板解析

代码示例

//获取配置的CutSameUIConfig
private val cutsameConfig: CutSameUIConfig? by lazy  {
    InnerEffectOneConfigList.getConfig()
}

//获取模板列表
val data = withContext(Dispatchers.IO) {
    val key = EOResourcePanelKey.CUTSAME_TEMPLATES.value
    cutsameConfig?.resourceLoader?.loadResourceList(key, key) ?: emptyList()
}

注意事项

剪同款模板素材如何使用素材SDK进行管理,参考:素材管理

获取TemplateItem

功能描述

根据模板包的路径,构造一个TemplateItem用于模板重演

接口定义

data class TemplateItem(
    @SerializedName("title") val title: String = "",
    @SerializedName("fragment_count") val fragmentCount: Int = 0,
    @SerializedName("md5") val md5: String = "",
    @SerializedName("zip_path") var zipPath: String = "", //zip文件的本地路径,用于离线模板
    @SerializedName("unzip_path") var unZipPath: String = "", //zip文件解压后的本地路径,用于离线模板
    @SerializedName("fragments") var fragments: List<TemplateFragment> = emptyList() //槽位的信息
)

代码示例

val templateItem = TemplateItem(
    md5 = pathMd5,
    unZipPath = result.absPath
)

模板对象&模板重演

创建模板对象

提供素材处理接口,一个模板视频制作周期内,使用同一个模板对象

功能描述

创建模板对象,首次创建CutSameSource对象时需要该对象

接口定义

/**
  * 模版资源对象
 * 模板支持传入zip包或者解压后的文件夹,两个字段二选一传入即可,都传的话优先使用zipPath
 *  @param  md5: 模版文件md5
 * @param zipPath
 * @param unzipPath
  */
data class SourceInfo(
    val md5: String,
    val zipPath: String = "",
    val unzipPath: String = ""
)
/**
  *  @param  sourceInfo: 模版资源对象
  */
fun createCutSameSource(sourceInfo: SourceInfo): CutSameSource

代码示例

//调用该接口使用SourceInfo对象创建CutSameSource对象
cutSameSource = CutSameSolution.createCutSameSource(
    SourceInfo(
        templateItem.md5,
        templateItem.zipPath,
        templateItem.unZipPath
    )
)

解析模板信息

功能描述

解析模板,获取模板的槽位信息

接口定义

fun prepareSource(
    listener: PrepareSourceListener)
    
    
 interface PrepareSourceListener {
     //模版准备进度
     fun onProgress(progress: Float)
     //模版准备成功,返回槽位信息
     fun onSuccess(mediaItemList: ArrayList<MediaItem>?,
                   textItemList: ArrayList<TextItem>?,
                   model: NLEModel
     )
     //模版准备失败
     fun onError(code: Int, message: String?)
}

代码示例

cutSameSource?.prepareSource(object : PrepareSourceListener {
    override fun onProgress(progress: Float) {
    }

    override fun onSuccess(
        mediaItemList: ArrayList<MediaItem>?,
        textItemList: ArrayList<TextItem>?,
        model: NLEModel
    ) {
        //填充mediaItemList的相关字段
    }

    override fun onError(code: Int, message: String?) {
      
    }
})

素材合成处理

功能描述

选择素材后,对选择的素材进行压缩、倒放等处理

接口定义

/**
  *  @param  processMediaItems: 选择后的素材列表
 * @param  compressSourceListener: 素材处理状态接口
  */
fun composeSource(
    processMediaItems: ArrayList<MediaItem>,
    compressSourceListener: ComposeSourceListener
)
//素材处理状态接口
interface ComposeSourceListener {
    // 处理失败
    fun onError(errorCode: Int, message: String?)
    // 处理进度
    fun onProgress(progress: Int)
    // 处理成功
    fun onSuccess(mediaItems: ArrayList<MediaItem>?)
}

代码示例

cutSameSource?.composeSource(data, object : ComposeSourceListener {
    override fun onError(errorCode: Int, message: String?) {
        //处理素材失败
    }

    override fun onProgress(progress: Int) {
        //处理素材进度
    }

    override fun onSuccess(mediaItems: ArrayList<MediaItem>?) {
        //处理素材成功
    }
})

创建播放对象

功能描述

创建CutSamePlayer对象,此对象提供视频预览、槽位编辑、文本编辑、视频导出等能力

接口定义

/**
 * 创建CutSamePlayer
  *  @param  surfaceView: 播放对象
 * @param  cutSameSource: 素材操作对象,如果是草稿导入的情况,此参数可空
  */
fun createCutSamePlayer(surfaceView: SurfaceView, cutSameSource: CutSameSource?): CutSamePlayer

代码示例

cutSamePlayer = CutSameSolution.createCutSamePlayer(videoSurfaceView, cutSameSource)

注意事项

  • 创建cutSamePlayer依赖于创建cutSameSource对象,所以需要先创建cutSameSource对象

  • cutSamePlayer使用完后需要调用release()释放资源

播放重演

功能描述

根据 模板&处理后的素材 生成实时预览的视频

接口定义

/**
  *  @param  mediaItems: 媒体素材
 * @param  textItems: 文本素材
 * @param  listener: 添加播放状态回调接口
  */
fun preparePlay(mediaItems: List<MediaItem>?, textItems: List<TextItem>?)

//PlayerStateListener注册方法
fun registerPlayerStateListener(playerStateListener: PlayerStateListener)
fun unRegisterPlayerStateListener(playerStateListener: PlayerStateListener)
//播放状态回调接口
interface PlayerStateListener {
    companion object {
        //数据准备之前状态
        const val PLAYER_STATE_IDLE = 1001
       //数据准备完成状态
        const val PLAYER_STATE_PREPARED = 1002
        //播放暂停状态
        const val PLAYER_STATE_PAUSED = 1004
        //正在播放状态
        const val PLAYER_STATE_PLAYING = 1005
        //播放错误状态
        const val PLAYER_STATE_ERROR = 1006
        //播放销毁状态
        const val PLAYER_STATE_DESTROYED = 1007

    }
    //首桢完成播放
    fun onFirstFrameRendered()
    //状态变化
    fun onChanged(state: Int)
    //播放进度
    fun onPlayProgress( process: Long)
    //播放结束
    fun onPlayEof()
    //播放对象错误
    fun onPlayError(what: Int, extra: Int)
}

代码示例

val listener = object : PlayerStateListener {
    override fun onFirstFrameRendered() {
    
    }

    override fun onChanged(player: BasePlayer, state: Int) {
        when (state) {
            PlayerStateListener.PLAYER_STATE_PREPARED -> {
                Log.d(TAG, "PLAYER_STATE_PREPARED")
                cutSamePlayer?.start()
            }
            PlayerStateListener.PLAYER_STATE_PLAYING -> {
                //正在播放状态
            }
            PlayerStateListener.PLAYER_STATE_ERROR -> {
                //播放错误状态
            }
            PlayerStateListener.PLAYER_STATE_IDLE -> {
                //数据准备之前状态
            }
            PlayerStateListener.PLAYER_STATE_PAUSED -> {
                //播放暂停状态
            }
            PlayerStateListener.PLAYER_STATE_DESTROYED -> {
                //播放销毁状态
            }
        }
    }

    override fun onPlayEof() {
        //播放结束
    }

    override fun onPlayError(player: BasePlayer, what: Int, extra: Int) {
        //播放对象错误
    }

    override fun onPlayProgress(player: BasePlayer, process: Long) {
        //播放进度
    }
}

cutSamePlayer?.preparePlay(mediaItemList, textItemList)

操作模板对象

获取模板媒体素材

功能描述

获取模板的媒体素材,即模板的可变槽位信息

接口定义

/**
 * 获取模版媒体素材
 * cutSamePlayer.getMediaItems()
 */
fun getMediaItems(): ArrayList<MediaItem>?
/**
 * 媒体素材数据结构
 * 不需业务赋值:业务不需要对extra或者CutSameSource.prepareSoure()返回的List<MediaItem>相关字段进行修改或者赋值。
 * 需业务赋值 :业务需要对extra或者CutSameSource.prepareSoure()返回的List<MediaItem>相关字段进行修改或者赋值。
 * 根据业务需求确认是否赋值:业务根据自身需求对extra或者CutSameSource.prepareSoure()返回的List<MediaItem>相关字段进行修改
 */
data class MediaItem(
    // ********* 属性 **************************
    var materialId  //定位project segment用,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : String,
    var targetStartTime // 素材槽位在模版的开始时间,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Long = 0,
    var isMutable // 素材槽位是否可变,true 表示可变,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Boolean,
    var alignMode // 视频素材对齐方式 "align_video" "align_canvas",必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : String = "",
    var isSubVideo // 是否副轨视频,非必须,不需业务赋值,不需业务赋值, 可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Boolean = false,
    var isReverse // 是否需要倒放,必须,不需业务赋值, 可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Boolean = false,
    var cartoonType // 漫画脸效果,非必须,不需业务赋值, 可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Int = 0,
    var width     // 宽,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Int,
    var height    // 高,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Int,
    var duration  // 时长,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Long,
   var oriDuration  // 替换素材的时长,必须,需业务赋值,在填充模版槽位信息时需要传入。
    : Long = 0,
    var source
    : String = "", // 素材路径 必须,需业务赋值,在填充模版槽位信息时需要传入。
    var sourceStartTime // 时间裁剪起始点,默认值为0,必须,根据业务需求确认是否赋值,extra或者CutSameSource.prepareSoure()回调中有值,如业务有视频裁剪需求,需要传入该值。
    : Long = 0,
    var cropScale: Float = 0f,// 素材缩放,必须,根据业务需求确认是否赋值,extra或者CutSameSource.prepareSoure()回调中有值,如业务有素材缩放需求,需要传入该值。
    var crop          // 空间裁剪区域 必须,根据业务需求确认是否赋值,extra或者CutSameSource.prepareSoure()回调中有值,如业务有素材缩放需求,需要传入该值。
    : ItemCrop = ItemCrop(0f,0f,0f,0f), 
    /**
          * [TYPE_VIDEO], [TYPE_PHOTO]
          */
    val type    // 视频类型,"photo"、"video" 必须,需业务赋值,在填充模版槽位信息时需要传入。
    : String = "",

    val mediaSrcPath // 素材原路径 必须,需业务赋值,在填充模版槽位信息时需要传入。
    : String = ""
    
    val targetEndTime // 素材在模版的结束时间,必须,不需业务赋值, 可从extra或者CutSameSource.prepareSoure()回调中获取。
    : Long = 0,

    val volume //音量 必须,根据业务需求确认是否赋值,extra或者CutSameSource.prepareSoure()回调中有值,如业务有音量调节需求,需要传入该值。
    : Float = 0f,

    val relation_video_group // 槽位分组,必须,不需业务赋值,可从extra或者CutSameSource.prepareSoure()回调中获取。
    : String = ""
)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
val mediaItems = cutSamePlayer?.getMediaItems()

更新媒体素材

功能描述

支持替换媒体素材功能,即替换槽位素材

接口定义

/**
 * 更新文本
  *  @param  materialId: 素材ID
 * @param  mediaItem: 媒体素材
  */
fun updateMedia(materialId: String, mediaItem: MediaItem)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
//repalcedMediaItem为通过素材替换页选择的素材
cutSamePlayer?.updateMedia(materialId,repalcedMediaItem)

获取播放文本素材

功能描述

获取模版文本素材

接口定义

/**
 * 获取模版文本素材
 */
fun getTextItems(): ArrayList<TextItem>?
/**
 * 模版文本素材数据结构
 */
data class TextItem(
    /**
          * 时长
          */
    val duration: Long = 0,
    /**
          * 是否可被更改
          */
    val mutable: Boolean = false,
    /**
          * 素材ID
          */
    val materialId: String = "",
    /**
          * 旋转角度
          */
    val rotation: Double = 0.0,
    /**
          * 展示的起始时间
          */
    val targetStartTime: Long = 0L,
    /**
          * 文本内容
          */
    var text: String = ""
)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
val textItems = cutSamePlayer?.getTextItems()

更新模版文本素材

功能描述

支持编辑模版文本功能

接口定义

/**
 * 更新文本
  *  @param  materialId: 素材ID
 * @param  text: 要修改的文本
  */
fun updateText(materialId: String, text: String)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
val textItems = cutSamePlayer?.updateText(materialId, "修改的文本")

播放控制

功能描述

支持控制播放,如开始、暂停、以及Seek到指定时间

接口定义

//开始播放
fun start()
//暂停播放
fun pause()
/**
 * 拖动到指定时间播放
  *  @param  position: 拖动到的位置 单位:ms
 * @param  isAutoPlay: 是否自动播放
  */
fun seekTo(position: Int, isAutoPlay: Boolean)
//调用播放控制接口也会触发该接口的回调
interface PlayerStateListener {
    companion object {
        //数据准备之前状态
        const val PLAYER_STATE_IDLE = 1001
       //数据准备完成状态
        const val PLAYER_STATE_PREPARED = 1002
        //播放暂停状态
        const val PLAYER_STATE_PAUSED = 1004
        //正在播放状态
        const val PLAYER_STATE_PLAYING = 1005
        //播放错误状态
        const val PLAYER_STATE_ERROR = 1006
        //播放销毁状态
        const val PLAYER_STATE_DESTROYED = 1007

    }
    //首桢完成播放
    fun onFirstFrameRendered()
    //状态变化
    fun onChanged(player: BasePlayer, state: Int)
    //播放进度
    fun onPlayProgress(player: BasePlayer, process: Long)
    //播放结束
    fun onPlayEof()
    //播放错误
    fun onPlayError(player: BasePlayer, what: Int, extra: Int)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
cutSamePlayer?.seekTo(timePos, true)
cutSamePlayer?.start()
cutSamePlayer?.pause()

设置某个片段的音量

接口定义

/**
  *  @param  materialId: 素材ID
 *  @param  volume: 音量值 0..1
 */
fun setVolume(materialId: String, volume: Float)

代码示例

volumeSliderView.setOnSliderChangeListener(object : OnSliderChangeListener() {
    override fun onChange(value: Int) {
        //....
    }

    override fun onBegin(value: Int) {
        //....
    }

    override fun onFreeze(value: Int) {
        selectMediaItem?.let  {
            //设置音量
            cutSamePlayer?.setVolume(it.materialId, value.toFloat() / 100)
        }
    }
})

获取某个片段的音量

接口定义

/**
  *  @param  materialId: 素材ID
 *  @return  Float: 音量值 
 */
fun getVolume(materialId: String): Float

代码示例

//音量view显示的时候获取音量
private fun showSlotVolumeLayout() {
    if (volumeLayout.visibility  == View.GONE) {
        selectMediaItem?.let  {
            //获取音量
            val volume = cutSamePlayer?.getVolume(it.materialId)?.times(100)?.toInt() ?: 0
            volumeSliderView.currPosition = volume
        }
        volumeLayout.visibility  = View.VISIBLE
    }
}

背景音频替换和音量调节

接口定义

interface ICutSameAudio {
    companion object {
        const val SUCCESS = 0

        /**
         * 输入参数不符合条件
         */
        const val PARAMS_ERROR = -1

        /**
         * 无效的音频文件信息
         */
        const val AUDIO_INFO_INVALID = -2

        /**
         * 无效音量值
         */
        const val INVALID_VOLUME = -1.0f
    }

    /**
     * 设置模板自定义音频
     * @param path 音频文件本地路径
     * @param audioName 音频名称 可选参数
     * @param fromTimeMs 从该音频文件哪个时间点开始播放,例如:原音频文件有3分钟,180s,但是模板音频只需要10s,
     * 这是我希望从选取副歌部分可能是100s-110s,那么该参数应该传 100 * 1000,单位是毫秒,如果希望从头开始就直接设置0.
     *
     * @return 错误码
     */
    fun setCustomAudio(path: String, audioName: String = "", fromTimeMs: Long): Int

    /**
     * 获取模板音频的起始时间
     * @return 单位ms
     */
    fun getTemplateAudioStartTime(): Long

    /**
     * 获取模板音频的总时长
     * @return 单位ms
     */
    fun getTemplateAudioDuration(): Long

    /**
     * 重置成原模板音频
     */
    fun resetAudio(): Int

    /**
     * 设置音量,如果有定制音乐,只设置定制音乐轨音量,如果无定制音乐轨,则设置原始音乐轨轨道
     * @param volume 0.0 - 1.0
     *
     * @return 错误码
     */
    fun setAudioVolume(volume: Float): Int

    /**
     * 获取当前音量,首先获取通过setAudioVolume(volume)接口设置过的音量,
     * 未调用过首先获取通过setAudioVolume(volume), 会先获取自定义音频的音量,
     * 未设置自定义音频时,会获取模板原始音频音量,优先获取首个关键帧的音量,其次是原始音频音量
     *
     * @return 对应音量值,如果找不到则返回
     * @see INVALID_VOLUME
     */
    fun getAudioVolume(): Float
}

代码示例

// 从 CutSamplyer 获取 音频操作接口
val cutSameAudio: ICutSameAudio = cutSamePlayer.getAudioManager()

//替换原来背景音乐
cutsameAudio.setCustomAudio("/sdcard/Android/data/[pacakge]/music.mp3", "audioName", 0L)

//设置音量 0.0~0.1 float
cutsameAudio.setAudioVolume(0.8f)

//还原原来音频
cutsameAudio.resetAudio()

//获取当前音量
cutsameAudio.getAudioVolume()

导出

导出视频到本地

功能描述

将重演后的视频导出到本地

接口定义

/**
 * 导出视频接口
  *  @param  outFilePath: 导出路径
 * @param  compileParam: 导出编码参数
 * @param  listener: 导出状态监听
  */
fun compileNLEModel(outFilePath: String, compileParam: CompileParam?, listener: CompileListener)
/**
 * 取消导出视频接口
 */
fun cancelCompile()
/**
 * 导出编码参数数据结构
  *  @param  resolution: 分辨率
 * @param  supportHwEncoder: true:硬编码 false 软编码
 * @param  bps: 视频码率
 *  @param  fps: 视频帧率
 * @param  gopSize: gop
 * @param  swMaxRate: swMaxRate
 * @param  swCRF: swCRF
 * @param  bitrateMode: bitrateMode
  */
data class CompileParam(
    val resolution: ExportResolution,
    val supportHwEncoder: Boolean,
    val bps: Int,
    val fps: Int,
    val gopSize: Int,
    val swMaxRate: Long,
    val swCRF: Int,
    val bitrateMode: VEVideoEncodeSettings.ENCODE_BITRATE_MODE
) : Parcelable
    
                        
 enum class ExportResolution(val label: String, val width: Int, val height: Int, val level: Int) {
    V_4K("4K", 3840, 2160, 4000),
    V_2K("2K", 2560, 1440, 2000),
    V_1080P("1080p", 1920, 1080, 1080),
    V_720P("720p", 1280, 720, 720),
    V_480P("480p", 858, 480, 480)
}

代码示例

val param = createCompileParam()
val outputVideoPath = "/storage/emulated/0/相机/20210528143142.mp4"
cutSamePlayer?.compileNLEModel(outputVideoPath, param, object : CompileListener {
        override fun onCompileDone() {
            Log.d(TAG, "onCompileDone")
            //导出完成
        }

        override fun onCompileProgress(progress: Float) {
            //导出进度
        }

        override fun onCompileError(
            error: Int,
            ext: Int,
            f: Float,
            msg: String?
        ) {
            //导出失败
        }
    })

视频抽帧

功能描述

获取某个时间点的截图

接口定义

/**
 * 更新文本素材
  *  @param  timeStamps: 要获取的时间点,单位毫秒
 * @param  width: 要获取的帧宽度
 * @param  height: 要获取的帧高度
 * @param  listener: 取帧回调接口
  */
fun getVideoFrameWithTime(timeStamps: IntArray, width: Int, height: Int, listener: GetImageListener)

代码示例

val cutSamePlayer: CutSamePlayer? = CutSameSolution.createCutSamePlayer(videoSurfaceView, sourceUrl)
cutSamePlayer?.getVideoFrameWithTime(timeStamps, width,height,
    object :GetImageListener{
        override fun onGetImageData(
            bytes: ByteArray?,
            pts: Int,
            width: Int,
            height: Int,
            score: Float
        ) {
            if (bytes != null) {
                val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
                bmp.copyPixelsFromBuffer(ByteBuffer.wrap(bytes))
                listener?.frameBitmap(pts.toString(), bmp)
            } else {
                cutSamePlayer?.cancelGetVideoFrames() // 抽帧结束后需要cancel,不然会停留在抽帧状态
            }
        }

    })