内容说明
1. OOP调用例子(推荐)
- 使用
XfxPlugin.lua的面向对象封装 - 展示通过
call方法和直接获取ffmpegOps对象两种方式 - 完整的视频处理示例
2. 直接调用例子
- 直接调用
Main类的方式 - 适合了解底层实现
3. 实际应用示例
包含多个实用场景:
- 提取MP4视频第一帧图片:从视频中提取第一帧并保存为图片
- 获取视频信息:获取视频的时长、分辨率、编码等信息
- 视频格式转换:将视频转换为不同格式
- 视频裁剪:截取视频的指定时间段
- 视频合并:将多个视频合并为一个
- 提取音频:从视频中提取音频轨道
FFMPEG 功能包括
- 提取视频帧:提取第一帧或指定时间的帧
- 获取视频信息:时长、分辨率、编码、帧率、比特率等
- 视频格式转换:支持多种视频格式转换
- 视频裁剪:截取指定时间段的视频
- 视频合并:合并多个视频文件
- 提取音频:从视频中提取音频轨道
- 消息回调:支持设置回调函数,接收处理进度和状态消息
OOP调用例子
-- ============================================
-- FFMPEG 视频处理示例
-- 演示如何使用 XfxPlugin.lua 调用 FfmpegOps 进行视频处理
-- ============================================
-- 方式一:使用 XfxPlugin.lua 面向对象封装(推荐)
-- ============================================
print('========== 方式一:使用 XfxPlugin.lua 封装 ==========')
-- 加载 XfxPlugin.lua 类
local xfxModule = require('lib/XfxPlugin')
-- 创建 XFX 对象实例
local xfx = xfxModule:new({
apkName = 'xfxPlugin-release.apk', -- APK 文件名
})
-- 获取 ffmpegOps 对象
local ffmpegOps = xfx:getOps('ffmpegOps')
if not ffmpegOps then
print('无法获取 ffmpegOps 对象')
return
end
-- 检查 FFMPEG 是否可用
local isAvailable = ffmpegOps.isFFmpegAvailable()
print('FFMPEG 是否可用: ' .. tostring(isAvailable))
if not isAvailable then
print('FFMPEG 不可用,无法继续')
return
end
-- 获取 FFMPEG 版本信息
local version = ffmpegOps.getFFmpegVersion()
print('FFMPEG 版本: ' .. tostring(version))
-- 设置消息回调函数(需要使用 Runnable 包装)
import('java.lang.Runnable')
local callbackCount = 0
ffmpegOps.setMessageCallback(
Runnable {
run = function()
callbackCount = callbackCount + 1
print('收到回调消息 #' .. callbackCount)
end
}
)
-- 示例:获取视频信息
print('\n--- 获取视频信息 ---')
local videoPath = '/sdcard/test.mp4'
local videoInfo = ffmpegOps.getVideoInfo(videoPath)
print('视频信息 (JSON): ' .. videoInfo)
-- 解析 JSON 信息(如果有 jsonLib)
if jsonLib then
local info = jsonLib.decode(videoInfo)
if info then
print('视频时长: ' .. tostring(info.duration) .. ' 秒')
print('视频分辨率: ' .. tostring(info.width) .. 'x' .. tostring(info.height))
print('视频编码: ' .. tostring(info.codec))
if info.fps then
print('帧率: ' .. tostring(info.fps) .. ' fps')
end
end
end
print('\n示例执行完成!')
直接调用例子
import('com.nx.assist.lua.LuaEngine')
-- ============================================
-- 方式二:直接调用方式(不推荐,但可以了解底层实现)
-- ============================================
print('========== 方式二:直接调用方式 ==========')
local loader = LuaEngine.loadApk('xfxPlugin-release.apk')
if not loader then
print('Failed to load APK')
return
end
local UtilCodeMain = loader.loadClass('com.xfx.plugin.Main')
if not UtilCodeMain then
print('Failed to load Class')
return
end
---- 初始化插件
-- local context = LuaEngine.getContext()
-- UtilCodeMain.init(context)
-- 获取 FfmpegOps
local ffmpegOps = UtilCodeMain.ffmpegOps()
-- 检查 FFMPEG 是否可用
local isAvailable = ffmpegOps.isFFmpegAvailable()
print('FFMPEG 是否可用: ' .. tostring(isAvailable))
-- 获取视频信息
local videoPath = '/sdcard/test.mp4'
local videoInfo = ffmpegOps.getVideoInfo(videoPath)
print('视频信息: ' .. videoInfo)
实际应用示例
local xfxModule = require('lib/XfxPlugin')
local xfx = xfxModule:new({apkName = 'xfxPlugin-release.apk'})
local ffmpegOps = xfx:getOps('ffmpegOps')
if not ffmpegOps then
print('无法获取 ffmpegOps 对象')
return
end
-- 检查 FFMPEG 是否可用
if not ffmpegOps.isFFmpegAvailable() then
print('FFMPEG 不可用,请检查环境')
return
end
-- ============================================
-- 示例 1:提取MP4视频第一帧图片(重点示例)
-- ============================================
print('========== 示例 1:提取MP4视频第一帧图片 ==========')
local function extractFirstFrameFromMP4(videoPath, outputImagePath)
print('开始提取视频第一帧...')
print('输入视频: ' .. videoPath)
print('输出图片: ' .. outputImagePath)
-- 使用同步方法提取第一帧
local success = ffmpegOps.extractFrame(videoPath, outputImagePath)
if success then
print('✓ 成功提取第一帧图片: ' .. outputImagePath)
-- 检查输出文件是否存在
local fileOps = xfx:getOps('fileOps')
if fileOps and fileOps.isFileExists(outputImagePath) then
local fileSize = fileOps.getSize(outputImagePath)
print('输出文件大小: ' .. tostring(fileSize) .. ' 字节')
end
else
print('✗ 提取第一帧失败')
end
return success
end
-- 使用示例
local videoPath = '/sdcard/test.mp4'
local outputImagePath = '/sdcard/video_first_frame.jpg'
local success = extractFirstFrameFromMP4(videoPath, outputImagePath)
-- -- 异步方式提取第一帧(不阻塞)
-- print('\n--- 使用异步方式提取第一帧 ---')
-- ffmpegOps.extractFrameAsync(videoPath, '/sdcard/video_first_frame_async.jpg')
-- print('异步任务已启动,将在后台执行')
-- ============================================
-- 示例 2:获取视频信息
-- ============================================
print('\n========== 示例 2:获取视频信息 ==========')
local function getVideoDetails(videoPath)
print('正在获取视频信息: ' .. videoPath)
local infoJson = ffmpegOps.getVideoInfo(videoPath)
print('视频信息 (JSON): ' .. infoJson)
if jsonLib then
local info = jsonLib.decode(infoJson)
if info then
print('\n【视频详细信息】')
if info.duration then
print('时长: ' .. tostring(info.duration) .. ' 秒')
end
if info.durationFormatted then
print('时长(格式化): ' .. tostring(info.durationFormatted))
end
if info.width and info.height then
print('分辨率: ' .. tostring(info.width) .. 'x' .. tostring(info.height))
end
if info.codec then
print('编码: ' .. tostring(info.codec))
end
if info.fps then
print('帧率: ' .. tostring(info.fps) .. ' fps')
end
if info.bitrate then
print('比特率: ' .. tostring(info.bitrate) .. ' kb/s')
end
if info.fileSize then
print('文件大小: ' .. tostring(info.fileSize) .. ' 字节')
end
end
end
return infoJson
end
local videoInfo = getVideoDetails('/sdcard/test.mp4')
-- ============================================
-- 示例 3:视频格式转换
-- ============================================
print('\n========== 示例 3:视频格式转换 ==========')
local function convertVideoFormat(inputPath, outputPath, targetFormat)
print('开始转换视频格式...')
print('输入: ' .. inputPath)
print('输出: ' .. outputPath)
print('目标格式: ' .. (targetFormat or '自动检测'))
local success = ffmpegOps.convertFormat(inputPath, outputPath, targetFormat)
if success then
print('✓ 视频格式转换成功')
else
print('✗ 视频格式转换失败')
end
return success
end
-- 将 MP4 转换为 AVI
-- convertVideoFormat('/sdcard/test.mp4', '/sdcard/test.avi', 'avi')
-- -- 异步转换(不阻塞)
-- ffmpegOps.convertFormatAsync('/sdcard/test.mp4', '/sdcard/test_async.avi', 'avi')
-- ============================================
-- 示例 4:视频裁剪(截取指定时间段)
-- ============================================
print('\n========== 示例 4:视频裁剪 ==========')
local function trimVideoSegment(inputPath, outputPath, startTime, duration)
print('开始裁剪视频...')
print('输入: ' .. inputPath)
print('输出: ' .. outputPath)
print('开始时间: ' .. tostring(startTime) .. ' 秒')
print('持续时间: ' .. tostring(duration or '到视频结束') .. ' 秒')
local success = ffmpegOps.trimVideo(inputPath, outputPath, startTime, duration)
if success then
print('✓ 视频裁剪成功')
else
print('✗ 视频裁剪失败')
end
return success
end
-- 裁剪视频:从第 10 秒开始,持续 30 秒
-- trimVideoSegment('/sdcard/test.mp4', '/sdcard/test_video_trimmed.mp4', 10.0, 30.0)
-- 裁剪视频:从第 5 秒开始到视频结束
-- trimVideoSegment('/sdcard/test.mp4', '/sdcard/test_video_from_5s.mp4', 5.0, nil)
-- 异步裁剪
-- ffmpegOps.trimVideoAsync('/sdcard/test.mp4', '/sdcard/test_video_trimmed.mp4', 10.0, 30.0)
-- ============================================
-- 示例 5:视频合并
-- ============================================
print('\n========== 示例 5:视频合并 ==========')
local function mergeVideoFiles(videoPaths, outputPath)
print('开始合并视频...')
print('输入视频数量: ' .. tostring(#videoPaths))
for i, path in ipairs(videoPaths) do
print(' 视频 ' .. i .. ': ' .. path)
end
print('输出: ' .. outputPath)
local success = ffmpegOps.mergeVideos(videoPaths, outputPath)
if success then
print('✓ 视频合并成功')
else
print('✗ 视频合并失败')
end
return success
end
-- 合并多个视频
-- local videoList = {
-- '/sdcard/video1.mp4',
-- '/sdcard/video2.mp4',
-- '/sdcard/video3.mp4'
-- }
-- mergeVideoFiles(videoList, '/sdcard/merged_video.mp4')
-- 异步合并
-- ffmpegOps.mergeVideosAsync(videoList, '/sdcard/merged_video.mp4')
-- ============================================
-- 示例 6:提取音频
-- ============================================
print('\n========== 示例 6:提取音频 ==========')
local function extractAudioFromVideo(videoPath, audioPath, audioFormat)
print('开始提取音频...')
print('输入视频: ' .. videoPath)
print('输出音频: ' .. audioPath)
print('音频格式: ' .. (audioFormat or '自动检测'))
local success = ffmpegOps.extractAudio(videoPath, audioPath, audioFormat)
if success then
print('✓ 音频提取成功')
else
print('✗ 音频提取失败')
end
return success
end
-- 提取音频为 MP3
-- extractAudioFromVideo('/sdcard/test.mp4', '/sdcard/test_audio.mp3', 'mp3')
-- 提取音频为 AAC
-- extractAudioFromVideo('/sdcard/test.mp4', '/sdcard/test_audio.aac', 'aac')
-- 异步提取
-- ffmpegOps.extractAudioAsync('/sdcard/test.mp4', '/sdcard/test_audio.mp3', 'mp3')
-- ============================================
-- 示例 7:提取指定时间的视频帧
-- ============================================
print('\n========== 示例 7:提取指定时间的视频帧 ==========')
local function extractFrameAtTime(videoPath, outputImagePath, timeOffset)
print('开始提取视频帧...')
print('输入视频: ' .. videoPath)
print('输出图片: ' .. outputImagePath)
print('时间偏移: ' .. tostring(timeOffset) .. ' 秒')
local success = ffmpegOps.extractFrame(videoPath, outputImagePath, timeOffset)
if success then
print('✓ 成功提取视频帧')
else
print('✗ 提取视频帧失败')
end
return success
end
-- 提取第 N 秒的帧
-- extractFrameAtTime('/sdcard/test.mp4', '/sdcard/video_frame_at_10s.jpg', 10.0)
-- ============================================
-- 示例 8:使用消息回调
-- ============================================
print('\n========== 示例 8:使用消息回调 ==========')
local function setupMessageCallback()
print('设置消息回调函数...')
local messageCount = 0
ffmpegOps.setMessageCallback(
Runnable {
run = function()
messageCount = messageCount + 1
print('收到 FFMPEG 消息回调 #' .. messageCount)
-- 在实际应用中,可以在这里处理进度更新、完成通知等
end
}
)
print('消息回调已设置')
-- 执行一个操作来触发回调
print('执行视频信息获取以触发回调...')
local videoPath = '/sdcard/test.mp4'
local info = ffmpegOps.getVideoInfo(videoPath)
print('视频信息获取完成')
end
-- setupMessageCallback()
-- ============================================
-- 示例 9:完整的视频处理流程
-- ============================================
print('\n========== 示例 9:完整的视频处理流程 ==========')
local function processVideoWorkflow(videoPath)
print('开始视频处理流程...')
print('视频路径: ' .. videoPath)
-- 步骤 1:检查 FFMPEG 是否可用
if not ffmpegOps.isFFmpegAvailable() then
print('✗ FFMPEG 不可用,终止流程')
return false
end
print('✓ FFMPEG 可用')
-- 步骤 2:获取视频信息
print('\n步骤 2:获取视频信息...')
local infoJson = ffmpegOps.getVideoInfo(videoPath)
print('视频信息: ' .. infoJson)
-- 步骤 3:提取第一帧作为缩略图
print('\n步骤 3:提取第一帧...')
local thumbnailPath = '/sdcard/video_thumbnail.jpg'
local success = ffmpegOps.extractFrame(videoPath, thumbnailPath)
if success then
print('✓ 缩略图已保存: ' .. thumbnailPath)
else
print('✗ 缩略图提取失败')
end
-- 步骤 4:提取音频(如果需要)
print('\n步骤 4:提取音频...')
local audioPath = '/sdcard/video_audio.mp3'
success = ffmpegOps.extractAudio(videoPath, audioPath, 'mp3')
if success then
print('✓ 音频已提取: ' .. audioPath)
else
print('✗ 音频提取失败')
end
print('\n视频处理流程完成!')
return true
end
-- 执行完整流程
processVideoWorkflow('/sdcard/test.mp4')
print('\n所有示例代码已展示完成!')
print('注意:实际使用时,请确保视频文件路径正确,并根据需要取消注释相应的示例代码。')
提取MP4视频第一帧图片
-- ============================================
-- 提取MP4视频第一帧图片 - 完整示例
-- ============================================
local xfxModule = require('lib/XfxPlugin')
local xfx = xfxModule:new({apkName = 'xfxPlugin-release.apk'})
local ffmpegOps = xfx:getOps('ffmpegOps')
if not ffmpegOps then
print('无法获取 ffmpegOps 对象')
return
end
-- 检查 FFMPEG 是否可用
if not ffmpegOps.isFFmpegAvailable() then
print('FFMPEG 不可用')
return
end
-- 视频文件路径
local videoPath = '/sdcard/test.mp4'
-- 输出图片路径(支持 jpg, png 等格式)
local outputImagePath = '/sdcard/video_first_frame.jpg'
-- 方法 1:使用同步方法(会阻塞直到完成)
print('方法 1:同步提取第一帧...')
local success = ffmpegOps.extractFrame(videoPath, outputImagePath)
if success then
print('✓ 成功提取第一帧图片')
print('输出文件: ' .. outputImagePath)
-- 检查文件是否存在
local fileOps = xfx:getOps('fileOps')
if fileOps and fileOps.isFileExists(outputImagePath) then
local fileSize = fileOps.getSize(outputImagePath)
print('文件大小: ' .. tostring(fileSize) .. ' 字节')
end
else
print('✗ 提取第一帧失败')
end
-- 方法 2:使用异步方法(不阻塞)
print('\n方法 2:异步提取第一帧...')
ffmpegOps.extractFrameAsync(videoPath, '/sdcard/video_first_frame_async.jpg')
print('异步任务已启动,将在后台执行')
-- 方法 3:提取指定时间的帧(例如第 10 秒)
print('\n方法 3:提取第 10 秒的帧...')
local success2 = ffmpegOps.extractFrame(videoPath, '/sdcard/video_frame_10s.jpg', 10.0)
if success2 then
print('✓ 成功提取第 10 秒的帧')
end
-- 方法 4:使用消息回调监听处理状态
print('\n方法 4:使用回调监听处理状态...')
import('java.lang.Runnable')
ffmpegOps.setMessageCallback(
Runnable {
run = function()
print('收到 FFMPEG 处理消息')
end
}
)
-- 执行提取操作
ffmpegOps.extractFrame(videoPath, '/sdcard/video_first_frame_with_callback.jpg')
print('提取操作完成(回调已触发)')
异步消息例子
local xfxModule = require('lib/XfxPlugin')
local xfx = xfxModule:new({apkName = 'xfxPlugin-release.apk'})
local ffmpegOps = xfx:getOps('ffmpegOps')
if not ffmpegOps then
print('无法获取 ffmpegOps 对象')
return
end
-- 检查 FFMPEG 是否可用
if not ffmpegOps.isFFmpegAvailable() then
print('FFMPEG 不可用')
return
end
-- 视频文件路径
local videoPath = '/sdcard/test.mp4'
-- 输出图片路径(支持 jpg, png 等格式)
local outputImagePath = '/sdcard/video_first_frame.jpg'
-- 使用异步方法(不阻塞)
print('\n异步提取第一帧...')
ffmpegOps.extractFrameAsync(videoPath, '/sdcard/video_first_frame_async.jpg')
print('异步任务已启动,将在后台执行')
-- 使用消息回调监听处理状态
print('\n使用回调监听处理状态...')
import('java.lang.Runnable')
ffmpegOps.setMessageCallback(
Runnable {
run = function()
print('收到 FFMPEG 处理消息')
end
}
)
sleep(30000)
注意事项
- 文件路径:确保输入视频文件存在且路径正确
- 输出路径:确保输出目录有写入权限
- 文件格式:输出图片格式由文件扩展名决定(.jpg, .png 等)
- 异步操作:异步方法不会阻塞脚本执行,适合长时间操作
- 回调函数:设置回调后,会在操作过程中触发,可用于显示进度
- 错误处理:建议在实际使用中添加错误处理和文件存在性检查
常用方法总结
| 方法名 | 说明 | 同步/异步 |
|---|---|---|
extractFrame() |
提取指定时间的帧 | 同步 |
getVideoInfo() |
获取视频信息 | 同步 |
convertFormat() |
视频格式转换 | 同步 |
convertFormatAsync() |
视频格式转换 | 异步 |
trimVideo() |
裁剪视频 | 同步 |
trimVideoAsync() |
裁剪视频 | 异步 |
mergeVideos() |
合并视频 | 同步 |
mergeVideosAsync() |
合并视频 | 异步 |
extractAudio() |
提取音频 | 同步 |
extractAudioAsync() |
提取音频 | 异步 |
setMessageCallback() |
设置消息回调 | – |
isFFmpegAvailable() |
检查 FFMPEG 是否可用 | 同步 |
getFFmpegVersion() |
获取 FFMPEG 版本 | 同步 |
1. 官方交流QQ群,添加多个不批。建议使用安卓手机或电脑申请。
飞云脚本圈: 586333520
Auto.js学习交流③群:286635606
Auto.js学习交流②群:712194666(满员)
IOS免越狱自动化测试群:691997586
2. 盗版,破解有损他人权益和违法作为,请各位会员支持正版。
3. 本站部分资源来源于用户上传和网络搜集,如有侵权请提供版权证明并联系站长删除。
4.如未特别申明,本站的技术性文章均为原创,未经授权,禁止转载/搬运等侵权行为。
5.全站所有付费服务均为虚拟商品,购买后自动发货。售出后概不接受任何理由的退、换。注册即为接受此条款。
6.如果站内内容侵犯了您的权益,请联系站长删除。
飞云脚本 » 【懒人精灵】小飞侠插件专题——FFMPEG音视频处理类
飞云脚本圈: 586333520

Auto.js学习交流③群:286635606
Auto.js学习交流②群:712194666(满员)
IOS免越狱自动化测试群:691997586
2. 盗版,破解有损他人权益和违法作为,请各位会员支持正版。
3. 本站部分资源来源于用户上传和网络搜集,如有侵权请提供版权证明并联系站长删除。
4.如未特别申明,本站的技术性文章均为原创,未经授权,禁止转载/搬运等侵权行为。
5.全站所有付费服务均为虚拟商品,购买后自动发货。售出后概不接受任何理由的退、换。注册即为接受此条款。
6.如果站内内容侵犯了您的权益,请联系站长删除。
飞云脚本 » 【懒人精灵】小飞侠插件专题——FFMPEG音视频处理类