You need to enable JavaScript to run this app.
导航
SDK视频导出接口介绍
最近更新时间:2025.04.09 15:49:55首次发布时间:2025.04.08 17:46:49
我的收藏
有用
有用
无用
无用
接口定义

功能模块作用方法注意事项必须调用

初始化

初始化EOExportManager

fun init(
    activity: ComponentActivity,
    surfaceView: SurfaceView? = null,
    previewSurfaceImage: Bitmap? = null,
    eoExportInitConfig: EOExportInitConfig = EOExportInitConfig(),
    callback: (suc: Boolean) -> Unit,
): EOExportManager

activity: 上下文,需要使用ComponentActivity
surfaceView:预览视频的SurfaceView,在某些不需要显示预览的场景下,可以不传
previewSurfaceImage:设置预览首帧
eoExportInitConfig:初始化导出参数(可不传)
callback: 初始化回调

暂停视频fun pause()

设置视频到指定时间

fun seekTo(position: Long,
  isSmooth: Boolean = false)

position:单位毫秒
isSmooth: 是否跟手

获取封面图

fun getVideoCoverImage( videoSize: EOVideoSize, completionBlock: (draftImg: String, framePosition: Long, isAlbumCover: Boolean) -> Unit )

videoSize:获取视频帧作为封图大小
completionBlock:
获取视频帧回调,默认从上游intent中读取,拿不到的话会取首帧

视频分辨率fun getVideoSize(): EOVideoSize?注意可能为null,未初始化成功

视频时长

fun geTotalVideoDuration(): Long?

单位:us
注意可能为null,未初始化成功

获取来源fun getEOExportModel(): EOExportModel?获取sdk来源数据模型

封面

视频抽帧

fun getVideoFrames(
    timestamps: VecLongLong,
    eoVideoSize: EOVideoSize,
    completionBlock: ((videoFrame: Bitmap?) -> Unit)?=null
)

timestamps:单位:ms 抽帧位置集合List,支持单帧,多帧
eoVideoSize:抽视频帧大小宽,高)

completionBlock:耗时操作

videoFrame: 抽帧的bitmap,可能多次调用,依赖timestamps

设置封面(从视频帧)

fun saveVideoFrame(
        videoSize:  EOVideoSize,
    saveToDraft: Boolean = true,
        savedBlock: ((  String?,  Long) ->  Unit)? =  null
)

videoSize*:保存视频帧封图大小(宽,高)*
saveToDraft:视频帧保存到草稿,默认回写

savedBlock*:耗时操作*

String?:保存视频帧路径String Long: 视频帧位置,单位ms

设置封面(从相册)

fun pickAlbum(
saveToDraft: Boolean = true,
completionBlock: ((String?, String?, Boolean) -> Unit))

从sdk内置相册选择封面图功能,只支持静图
saveToDraft:视频帧保存到草稿,默认回写

completionBlock

参数1 String:选择并裁剪成功后的图片路径
  参数2 String:错误信息 参数3 Boolean:是否取消

导出

是否添加水印

fun shouldAddWaterMark
(shouldAddWaterMark: Boolean = true)

shouldAddWaterMark:默认添加

设置水印图片fun setWaterMarkPath(waterMarkPath: String?)waterMarkPath: 水印路径,只支持sdcard

设置水印图片大小

fun setWaterMarkSize(videoSize: EOVideoSize)

videoSize:水印图片大小,单位dp
(根据自己ux设计指定)

导出视频

fun exportVideo(
    outputPath: String,
    outputSetting: [EoOutputVideoSettings](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-XhisdcJWYo2J3Oxpuh1c7XH0nyb)= EoOutputVideoSettings(),
    exportListener: [IEoExportListener](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-LxcPdwDDMoknedxBax6cFEWGnnh)? = null
)

outputPath:导出视频保存路径
outputSetting:导出配置项
exportListener:导出监听

取消导出fun cancelExport()cancel回调

初始化

接口名称

fun init(
    activity: ComponentActivity,
    surfaceView: SurfaceView? = null,
    previewSurfaceImage: Bitmap? = null,
    eoExportInitConfig: EOExportInitConfig = EOExportInitConfig(),
    callback: (suc: Boolean) -> Unit,
): EOExportManager

参数说明

参数名称参数类型默认值是否必须说明
activityComponentActivitypickAlbum接口需要依赖,从相册选择封图需要使用,用于关注宿主生命状态,做一些资源释放操作
surfaceViewSurfaceViewnull用于在编辑过程中预览视频的SurfaceView,在某些不需要显示预览的场景下,可以不传
previewSurfaceImageBitmapnull设置预览帧,主要用于首帧优化

eoExportInitConfig

EOExportInitConfig

EOExportInitConfig()

/**
  * 导出初始化配置,
  *  @property previewCompileFinishPage 预览和导出功能,一次导出完成后就finish页面,SurfaceView不能为空
  *  @property autoReleaseCompileDone 导出完成后是否自动释放内存
  */
data class EOExportInitConfig(
var previewCompileFinishPage :Boolean = false,
var autoReleaseCompileDone :Boolean = true
)

返回值说明

返回值类型说明
EOExportManager编辑实例,所有编辑相关的接口都在这个Manager里面

示例代码

private lateinit var eoExportManager:EOExportManager

override fun onViewCreated(
        view:  View,
        savedInstanceState:  Bundle?,

)  {
    super.onViewCreated(view, savedInstanceState)
    //>>>> step1 初始化EOExportManager
    eoExportManager.init(requireActivity(), view.findViewById<SurfaceView>(R.id.export_cover_preview))  {  suc  ->
    if  (!suc) {
                        requireActivity().finish()
                }
    }
}

预览

获取封面图

接口名称

fun getVideoCoverImage(
    videoSize: EOVideoSize,
    completionBlock: (draftImg: String, framePosition: Long, isAlbumCover: Boolean) -> Unit
)

参数说明

参数名称参数类型默认值是否必须说明
videoSizeEOVideoSize抽取视频帧的大小封图(宽,高)
completionBlock(draftImg: String, framePosition: Long, isAlbumCover: Boolean) -> Unit设置预览帧,主要用于首帧优化

返回值说明

返回值类型说明

(draftImg: String, framePosition: Long, isAlbumCover: Boolean)

获取草稿封图和视频帧图
draftImg:草稿箱或者取自视频帧
framePosition(单位ms:draftImg取视频中的位置,如果相册为0
isAlbumCover: true: draftImg来源于相册,false:draftImg来源于视频帧

示例代码

eoExportManager.getVideoCoverImage {  draftImg, framePosition, isAlbumCover ->
    if (isAlbumCover) {
        //updateCoverAlbum(draftImg)
    } else {
        //updateCoverFrame(draftImg, framePosition)
    }
}

暂停

接口名称

fun pause()

参数说明

返回值说明

示例代码

eoExportManager.pause()

设置视频指定位置

接口名称

fun seekTo(position: Long, isSmooth: Boolean = false)

参数说明

参数名称参数类型默认值是否必须说明
positionLong设置视频的位置,单位ms
isSmoothBooleanfalse设置视频过程中是否跟手滑动

返回值说明

示例代码

eoExportManager.seekTo(position, isSmooth)

获取视频分辨率

接口名称

fun getVideoSize(): EOVideoSize?

参数说明

返回值说明

返回值类型说明
EOVideoSize获取视频分辨率(宽和高)

示例代码

val eoVidoeSize = eoExportManager.getVideoSize()
eoVidoeSize?.let{
    Log.d("Tag"," width = ${eoVidoeSize.width}, height = ${eoVidoeSize.height}")
}

时长

接口名称

fun geTotalVideoDuration(): Long?

参数说明

返回值说明

返回值类型说明
Long获取视频时长

示例代码

val videoDuration = eoExportManager.geTotalVideoDuration()
eoVidoeSize?.let{
    Log.d("Tag"," videoDuration = $videoDuration")
}

获取来源Model

接口名称

fun getEOExportModel(): EOExportModel?

参数说明

返回值说明

返回值类型说明

EOExportModel

获取EffectOne上游数据模型,主要用户业务方使用,

@Parcelize
data class EOExportModel(
//草稿页封图地址,需要业务关闭时候透传回来
 var draftImg: String,
 //标记封图来源,是相册还是视频帧(true相册,false:视频帧),需要业务关闭时候透传回来
 var isAlbumCover: Boolean = false,
 //视频帧封图位置
  var framePosition: Long = 0
) : Parcelable

示例代码

val exportViewModel = eoExportManager.getEOExportModel() ?: return
val totalDuration =  eoExportManager.geTotalVideoDuration() ?: return
exportViewModel.takif(it.isAlbumCover.not)?.let{
    //业务保存视频帧做封面后,退出页面,再次打开,重新选择视频帧时候,希望seek到上次保存视频帧的位置
    eoExportManager.seekTo(it.framePosition,false)
}

封面

抽帧

接口名称

fun getVideoFrames(
    timestamps: VecLongLong,
    eoVideoSize: EOVideoSize,
    completionBlock: ((videoFrame: Bitmap?) -> Unit)?=null
)

参数说明

参数名称参数类型默认值是否必须说明
timestampsVecLongLong抽帧视频位置序列集合List,支持单帧,多帧
eoVideoSizeEOVideoSize抽取视频的大小,(宽,高)

completionBlock

((videoFrame: Bitmap?) -> Unit)

null

耗时操作

videoFrame: 成功抽帧返回bitmap,可能多次调用,依赖timestamps

返回值说明

返回值类型说明
Bitmap成功抽帧返回bitmap,可能多次调用,回调次序按照timestamps添加顺序

示例代码

eoExportManager.getVideoFrames(
    VecLongLong(listOf(0)),
    EOVideoSize(720, 1080)
) {  bmp ->
    runOnUiThread  {
        bmp?.let  {
            //
        }
        }
}

设置封面(从视频帧)

接口名称

fun saveVideoFrame(
        videoSize:  EOVideoSize,
        saveToDraft:  Boolean  =  true,
        savedBlock: ((  String?,  Long) ->  Unit)? =  null
)

参数说明

参数名称参数类型默认值是否必须说明
videoSizeEOVideoSize抽取视频的大小,(宽,高)
saveToDraftBooleantrue保存视频帧到草稿箱封面,用户草稿页展示

savedBlock

((String?, Long) -> Unit)

null

保存当前视频帧 String?:保存视频帧路径String Long: 视频帧位置,单位ms

返回值说明

返回值类型说明
(( String?, Long) -> Unit)String?:保存视频帧路径String Long: 视频帧位置,单位ms

示例代码

eoExportManager.saveVideoFrame(EOVideoSize(720, 1080)){
 loading, bitmapPath, position ->{
    
    }
}

设置封面(从相册)

接口名称

fun pickAlbum(saveToDraft:  Boolean  =  true,
    completionBlock: ((String?, String?, Boolean) -> Unit))

参数说明

参数名称参数类型默认值是否必须说明
saveToDraftBooleantrue保存相册图片到草稿箱封面,用户草稿页展示

completionBlock

((String?, String?, Boolean) -> Unit)

从sdk内置相册选择封面图功能,只支持静图

String: String: Boolean*:*

返回值说明

返回值类型说明

((Boolean, String?, Long) -> Unit)

参数1 String:选择并裁剪成功后的图片路径
参数2 String:错误信息 参数3 Boolean:是否取消

示例代码

eoExportManager.pickAlbum {  bitmapPath: String?, errorMsg: String?, cancel: Boolean ->
    bitmapPath?.let  {
        Log.d("Tag","bitmapPath ->  $it  ")
    }
}

导出

水印

概述:SDK只接受本地路径的输入,不接受res资源的输入
因此 需要提前将水印图片下载到本地SD卡上或者内置到app中 再拷贝数据到SD卡上
位置:水印默认显示视频总时长,前半视频左上,后半视频右下

添加水印

接口名称
fun shouldAddWaterMark(shouldAddWaterMark: Boolean = true)
参数说明
参数名称参数类型默认值是否必须说明
shouldAddWaterMarkBooleantrue导出视频是否添加水印
返回值说明

示例代码
eoExportManager.shouldAddWaterMark(true)

设置水印图片

接口名称
fun setWaterMarkPath(waterMarkPath: String?)
参数说明
参数名称参数类型默认值是否必须说明
waterMarkPathString设置导出视频水印图片路径
返回值说明

示例代码
eoExportManager.setWaterMarkPath("/sdcard/Download/waterMark/eo-waterMark.jpg")

设置水印图片大小

接口名称
fun setWaterMarkSize(videoSize: EOVideoSize)
参数说明
参数名称参数类型默认值是否必须说明

videoSize

EOVideoSize

EEOVideoSize(134,32)

设置导出视频水印图片大小:

单位:dp,根据UI设计师给定大小
  偏移(24,32)不可修改

返回值说明

示例代码
eoExportManager.setWaterMarkSize(EOVideoSize(width =  29, height =  31))

完成导出

导出视频

接口名称
fun exportVideo(
    outputPath: String,
    outputSetting: [EoOutputVideoSettings](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-XhisdcJWYo2J3Oxpuh1c7XH0nyb)= EOOutputVideoSettings(),
    exportListener: [IEoExportListener](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-LxcPdwDDMoknedxBax6cFEWGnnh)? = null
)
参数说明
参数名称参数类型默认值是否必须说明
outputPathString导出视频的路径,比如相册等

outputSetting

EoOutputVideoSettings

EOOutputVideoSettings()

导出参数设置

data class EOOutputVideoSettings(
    var outputFps: [EOFps](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-AIpmdd0a7oiGG4xLMEncOBdvnOg) = EOFps.FPS_30,
    var outputRes: [EOResolution](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-WIqRd5OLhoYZkCxOMaJczyGpnTb) = EOResolution.RES_720P,
    // 是否使用软解码,低端机或者或硬解硬编不足,根据业务方自行调整,默认开启软解
    var useSoftwareDecode: Boolean = true,
    // 是否使用硬编码 默认开启
    var useHWEncoder: Boolean = true,
    //码率,默认为高码率,
    //可根据需要自行调整
    //码率设置参考「视频生产码率参考表」
    var bps: Int? = null
)

【EO】视频生产码率参考表

exportListener

IEoExportListener

null

导出视频回调

interface IEOExportListener {
    /**
          * {zh}导出出错
          *  @param error 错误码
          *  @param msg 错误消息
          */
    fun onError(error: Int, msg: String?)
    /**
          * {zh}导出成功
          */
    fun onDone()
    /**
          * {zh}导出出错
          *  @param progress 进度 0~1
          */
    fun onProgress(progress: Float)
}
返回值说明
示例代码
val saveDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath
val dateFormat = SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault())
val exportFileName = "eo-${dateFormat.format(Date())}.mp4"

val exportFilePath = "$saveDir${File.separator}$exportFileName"
eoExportManager.exportVideo(
    outputPath = exportFilePath,
    outputSetting = EOOutputVideoSettings(),
    exportListener = iEOExportListenerImpl,
)



private val iEOExportListenerImpl by lazy  {
    object : EOExportListenerAdapter() {
        override fun onDone() {
            Log.d(TAG, "onCompileDone()")
        }

        override fun onError(error: Int,  msg: String?) {
            Log.d(TAG,"onCompileError() error = $error, msg = $msg")
        }

        override fun onProgress(progress: Float) {
            Log.d( TAG,"onCompileProgress() progress =${progress.times(100).toInt()}" )
        }
    }
}

导出图片

导出图片功能是在导出视频功能 fun exportVideo() 的基础上实现的,在完成视频导出之后,通过导出视频帧的方式完成图片的导出

接口名称

同上(导出视频)

参数说明

同上(导出视频)

示例代码
// 创建临时视频文件和导出图片文件
val dateFormat = SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault())

val exportTempFileName = "eo-${dateFormat.format(Date())}.mp4"
val tempFileDir = EOUtils.pathUtil.externalDir("temp_export").absolutePath
val tempPath = File(tempFileDir, exportTempFileName)

val exportFileName = "eo-${dateFormat.format(Date())}.jpg"
val photoFileDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)?.toString()
val photoPath = File(photoFileDir, exportFileName)

// 执行导出视频
eoExportViewModel.eoExportManager.exportVideo(
    outputPath = tempPath.absolutePath,
    outputSetting = EOOutputVideoSettings().apply {
        eoVideoEncodeViewModel.resolutionFps.value?.let {
            outputRes = it.first
            outputFps = it.second
        }
        useSoftwareDecode = true
        useHWEncoder = true

    },
    exportListener = EOExportImageListener(activity, photoPath)
)

// 处理导出视频文件的listener
class EOExportImageListener(
    private val activity: Activity,
    private val photoPath: File,
) : EOExportDefaultListener() {

    override fun onDone(outputPath: String) {   
        saveFrameAsPhoto(outputPath, photoPath)
        
        // 删除临时视频文件
        val tempVideoFile = File(outputPath)
        if (tempVideoFile.exists()) {
            tempVideoFile.delete()
            MediaScannerConnection.scanFile(activity,
                arrayOf(tempVideoFile.absolutePath),
                null
            ) {_, _ ->
                LogKit.d(TAG, "temp video file delete succeed: ${tempVideoFile.absolutePath}")
            }
        }
    }

    override fun onError(error: Int, msg: String?, ) {
        LogKit.d(TAG, "onCompileError() called with: error = $error, msg = $msg")
    }

    override fun onProgress(progress: Float) {
        LogKit.d(TAG, "onCompileProgress() : progress = ${progress.times(100).roundToInt()}")
    }

    private fun saveFrameAsPhoto(tempPath: String?, photoPath: File){
        if (tempPath == null) return
        val retriever = MediaMetadataRetriever()
        try {
            retriever.setDataSource(tempPath)
            val frameBitmap = retriever.getFrameAtTime(0)
            val outStream = FileOutputStream(photoPath)
            frameBitmap?.compress(Bitmap.CompressFormat.JPEG, 100, outStream)
            MediaScannerConnection.scanFile(activity, arrayOf(photoPath.absolutePath), null) { _, _ ->
                // 导出图片成功
                LogKit.d(TAG, "onCompileDone() outputPath  $photoPath")
            }
            outStream.close()

        } catch (e: Exception) {
            // 导出图片失败
            LogKit.e(TAG, "Get first frame from video failed.", e)
        } finally {
            retriever.release()
        }
    }

取消导出

接口名称
fun cancelExport()
参数说明

返回值说明

示例代码
eoExportManager.cancelExport()
导出页定制

导出页简介,可以参考EffectOne导出页简介

配置启动Action

const val  ACTION_EXPORT_ACTIVITY = "com.volcengine.effectone.Launch.EOExport"
//AndroidManifest.xml
<activity
    android:name=".export.EffectOneExportActivity"
    android:exported="true"
    android:screenOrientation="portrait"
    android:theme="@style/Theme.EffectOne">
    <intent-filter>
        <action android:name="com.volcengine.effectone.Launch.EOExport" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

自定义导出文件metadata(可选)

接口名称
fun setMetadata(metadata: Map<String, String>)
参数说明
参数名称参数类型默认值是否必须说明
metadataMap<String, String>以<key, value>的形式传入需要自定义的metadata数据
示例代码
val customMetadata = mutableMapOf<String, String>()
customMetadata["metadata_key_1"] = "metadata_value_1"
customMetadata["metadata_key_2"] = "metadata_value_2"
customMetadata["metadata_key_3"] = "metadata_value_3"

eoExportManager.setMetadata(customMetadata)    // 需在导出视频之前调用
// ...
eoExportManager.exportVideo()

准备水印资源(可选)

概述:SDK只接受本地路径的输入,不接受res资源的输入
因此 需要提前将水印图片下载到本地SD卡上或者内置到app中 再拷贝数据到SD卡上


//假设业务水印资源放到assets目录下
// 业务方自己实现,具体可见sample示例代码
EffectOneExportActivity.copyWaterMark(this)

Step 1 初始化EOExportManager

private lateinit var eoExportManager:EOExportManager

override fun onViewCreated(
        view:  View,
        savedInstanceState:  Bundle?,

)  {
    super.onViewCreated(view, savedInstanceState)
    //>>>> step1 初始化EOExportManager
    eoExportManager.init(requireActivity(), view.findViewById<SurfaceView>(R.id.export_cover_preview))  {  suc  ->
    if  (!suc) {
                        requireActivity().finish()
                }
    }
}

Step 2 导出

val saveDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath
val dateFormat = SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault())
val exportFileName = "eo-${dateFormat.format(Date())}.mp4"

val exportFilePath = "$saveDir${File.separator}$exportFileName"
 eoExportManager.exportVideo(
    outputPath = exportFilePath,
    outputSetting = EOOutputVideoSettings(),
    exportListener = iEOExportListenerImpl,
)



private val iEOExportListenerImpl by lazy  {
    object : EOExportDefaultListener() {
        override fun onDone() {
            Log.d(TAG, "onCompileDone()")
        }

        override fun onError(error: Int,  msg: String?) {
            Log.d(TAG,"onCompileError() error = $error, msg = $msg")
        }

        override fun onProgress(progress: Float) {
            Log.d( TAG,"onCompileProgress() progress =${progress.times(100).toInt()}" )
        }
    }
}
依赖数据模型

导出配置参数

/**
  * 导出初始化配置,
  *  @property previewCompileFinishPage 预览和导出功能,一次导出完成后就finish页面,
             SurfaceView不能为空
  *  @property autoReleaseCompileDone 导出完成后是否自动释放内存
  */
data class EOExportInitConfig(
    var previewCompileFinishPage :Boolean = false, 
    var autoReleaseCompileDone :Boolean = true
)

预览编辑和导出通信(EOExportModel)

@Parcelize
data class EOExportModel(
    var draftData: String = "",
    var draftImg: String,//草稿页封图地址,需要业务关闭时候透传回来
    var draftId: String,
    var isAlbumCover: Boolean = false,//标记封图来源,是相册还是视频帧(true相册,false:视频帧),需要业务关闭时候透传回来
    var framePosition: Long = 0//视频帧封图位置,需要业务关闭时候透传回来
) : Parcelable

视频大小(EOVideoSize)

data class EoVideoSize(
    @androidx.annotation.IntRange(from = 1) val width: Int = 720,
    @androidx.annotation.IntRange(from = 1) val height: Int = 1280
)

导出配置项(EOOutputVideoSettings)

data class EOOutputVideoSettings(
    var outputFps: [EOFps](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-AIpmdd0a7oiGG4xLMEncOBdvnOg) = EOFps.FPS_30,
    var outputRes: [EOResolution](https://bytedance.larkoffice.com/docx/A3ogdjxYkoREIdx6S8ScZc3wnTb#part-WIqRd5OLhoYZkCxOMaJczyGpnTb) = EoResolution.RES_720P,
    // 是否使用软解码,低端机或者或硬解硬编不足,根据业务方自行调整,默认开启软解
    var useSoftwareDecode: Boolean = true,
    // 是否使用硬编码 默认开启
    var useHWEncoder: Boolean = true,
)

导出分辨率(EOResolution)

enum class EOResolution(
    val resValue: String,
) {
    RES_540P("540p"),
    RES_720P("720p"),
    RES_1080P("1080p"),
    RES_4K("4k"),;
}

导出FPS(EOFps)

enum class EOFps(val fpsValue: String, val value: Int) {
    FPS_25("25 FPS", 25),
    FPS_30("30 FPS", 30),
    FPS_50("50 FPS", 50),
    FPS_60("60 FPS", 60),
}

导出回调监听(IEOExportListener)

interface IEOExportListener {
    /**
          * {zh}导出出错
          *  @param error 错误码
          *  @param msg 错误消息
          */
    fun onError(error: Int, msg: String?)
    /**
          * {zh}导出成功
          */
    fun onDone()
    /**
          * {zh}导出出错
          *  @param progress 进度 0~1
          */
    fun onProgress(progress: Float)
}