当前位置: 首页 > news >正文

制作和淘宝商城一样网站seo站长教程

制作和淘宝商城一样网站,seo站长教程,网页的分类,wordpress可以上传网页吗目录 前言 一、环境 二、创建APP 三. 添加FFmpeg库文件到app中 1. 复制ffmpeg头文件和so库到app中 2. 修改CMakeLists.txt文件内容. 3. 修改ffmpeglib.cpp 文件内容 4. 修改NativeLib.kt 文件添加方法和加载库 5. 调用 四. 增加解析视频文件信息功能 总结 前言 前面…

目录

前言

一、环境

二、创建APP

三. 添加FFmpeg库文件到app中

1. 复制ffmpeg头文件和so库到app中

2. 修改CMakeLists.txt文件内容.

3. 修改ffmpeglib.cpp 文件内容

4. 修改NativeLib.kt 文件添加方法和加载库

5. 调用

四. 增加解析视频文件信息功能

总结


前言

        前面有一篇记录了windows上👉 编译Android平台使用的FFmpeg库。想知道的同学可以去看一下😄。这一篇记录一下在android app上怎么使用这些库。


一、环境

  1. 安装Android studio, 方法就不介绍了,网上太多安装的方法了。
  2. 安装NDK和cmake,直接使用SDK monitor安装。 看过我的编译ffmpeg库的知道用的ndk 版本是:
    25.1.8937393

cmake版本:3.22.1

二、创建APP

android studio 创建module

创建成功后,目录结构跟下面差不多,只是没有assets和cpp这两个文件夹和NatvieLib文件。后面会说这两个文件夹和文件是干嘛的

 

三. 添加FFmpeg库文件到app中

1. 复制ffmpeg头文件和so库到app中

使用过NDK项目的都知道cpp这个是放CMakeLists.txt和所有的cpp文件的。

cpp这个文件夹下面创建一个ffmpeg文件夹用来放ffmpeg的头文件和so库文件。因为只编译了一个arm64-v8a 架构,所在在lib这个文件夹下面创建一个arm64-v8a用于放so库。目录结构如下图:

2. 修改CMakeLists.txt文件内容.

修改CMakeLists.txt文件内容编译ffmpeglib.cpp文件。

CMakeLists.txt文件内容如下,都添加注释了,不多说了。有不太清楚的可以自己创建一个Native library module,比对一下看看

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html.
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.# Sets the minimum CMake version required for this project.
cmake_minimum_required(VERSION 3.22.1)# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
# Since this is the top level CMakeLists.txt, the project name is also accessible
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
# build script scope).
project("ffmpeglib")#设定ffmpeg的头文件和so库文件到一个变量中
set(FFMPEG_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/../cpp/ffmpeg/include)
set(FFMPEG_LIB_DIR ${CMAKE_SOURCE_DIR}/../cpp/ffmpeg/lib/${ANDROID_ABI})# 输出调试信息,用于查看路径是否正确
message(STATUS "FFMPEG_INCLUDE_DIR: ${FFMPEG_INCLUDE_DIR}")
message(STATUS "FFMPEG_LIB_DIR: ${FFMPEG_LIB_DIR}")# 检查库文件是否存在
file(GLOB FFMPEG_LIB_FILES "${FFMPEG_LIB_DIR}/*.so")
if(NOT FFMPEG_LIB_FILES)message(FATAL_ERROR "No FFmpeg library files found in ${FFMPEG_LIB_DIR}. Please check the paths and ensure the libraries exist.")
endif()# 包含FFmpeg头文件,只有包含头文件后,在cpp中才能正确引用头文件
include_directories(${FFMPEG_INCLUDE_DIR})# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
add_library(${CMAKE_PROJECT_NAME} SHARED# List C/C++ source files with relative paths to this CMakeLists.txt.ffmpeglib.cpp)# 显式指定库文件路径
set(avformat_LIBRARY ${FFMPEG_LIB_DIR}/libavformat.so)
set(avcodec_LIBRARY ${FFMPEG_LIB_DIR}/libavcodec.so)
set(avutil_LIBRARY ${FFMPEG_LIB_DIR}/libavutil.so)
set(swresample_LIBRARY ${FFMPEG_LIB_DIR}/libswresample.so)
set(swscale_LIBRARY ${FFMPEG_LIB_DIR}/libswscale.so)
set(avdevice_LIBRARY ${FFMPEG_LIB_DIR}/libavdevice.so)
set(avfilter_LIBRARY ${FFMPEG_LIB_DIR}/libavfilter.so)# 检测so库文件,输出找到的库文件路径, c++引用so库是不用带lib前缀和.so扩展名的
foreach (LIB avformat avcodec avutil swresample swscale avdevice avfilter)if(EXISTS ${${LIB}_LIBRARY})message(STATUS "${LIB}_LIBRARY: ${${LIB}_LIBRARY}")else()message(FATAL_ERROR "${LIB}_LIBRARY not found at ${${LIB}_LIBRARY}. Please check the paths and ensure the libraries exist.")endif()
endforeach()#链接库文件
target_link_libraries(${CMAKE_PROJECT_NAME}${avutil_LIBRARY}${swresample_LIBRARY}${swscale_LIBRARY}${avcodec_LIBRARY}${avdevice_LIBRARY}${avfilter_LIBRARY}${avformat_LIBRARY}# List libraries link to the target libraryc++_sharedandroidlog)

3. 修改ffmpeglib.cpp 文件内容

添加一个initFfmpeg 方法用来初始化ffmpeg

extern "C" JNIEXPORT void JNICALL
Java_com_bob_ffmpegdemo_NativeLib_initFfmpeg(JNIEnv *env, jobject /* this */) {// 初始化 FFmpegavformat_network_init();// 打印 FFmpeg 版本信息到日志const char *version = avformat_configuration();LOGD("FFmpeg version: %s", version);
}

4. 修改NativeLib.kt 文件添加方法和加载库

package com.bob.ffmpegdemoclass NativeLib {/*** A native method that is implemented by the 'ffmpglib' native library,* which is packaged with this application.*/external fun stringFromJNI(): Stringexternal fun initFfmpeg()companion object {// Used to load the 'ffmpeglib' library on application startup.init {System.loadLibrary("ffmpeglib")}}
}

5. 调用

可以在Activity文件中直接调用NativeLab这个类中和方法

    override fun onResume() {super.onResume()testFfmpeg()}private fun testFfmpeg() {val nativeLib = NativeLib()Log.d(TAG, "-------- ${nativeLib.stringFromJNI()}")nativeLib.initFfmpeg()}

直接运行app, 成功会输出下面的内容

四. 增加解析视频文件信息功能

通过前面三节内容后,ffmpeg的库就添加到app中了,但是只是输出了ffmpeg 编译的信息。不知道ffmpeg的功能是否能用。这节增加解析视频文件的功能

  •  直接在ffmpeglib.cpp文件中添加testOpenVideo方法解析视频
extern "C" JNIEXPORT jstring JNICALL
Java_com_bob_ffmpegdemo_NativeLib_testOpenVideo(JNIEnv *env, jobject /* this */, jstring filePath) {const char *path = env->GetStringUTFChars(filePath, NULL);// 添加 'file://' 前缀以确保正确解析路径std::string full_path = "file://" + std::string(path);LOGD("Attempting to open video file: %s", full_path.c_str());AVFormatContext *pFormatCtx = nullptr;int ret = avformat_open_input(&pFormatCtx, full_path.c_str(), NULL, NULL);if (ret < 0) {char errbuf[AV_ERROR_MAX_STRING_SIZE];av_strerror(ret, errbuf, sizeof(errbuf));LOGE("Failed to open video file: %s", errbuf);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF("Failed to open video file.");}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {LOGE("Failed to retrieve stream information.");avformat_close_input(&pFormatCtx);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF("Failed to retrieve stream information.");}// 使用正确的函数名 av_dump_formatav_dump_format(pFormatCtx, 0, full_path.c_str(), 0); // 打印格式信息到标准输出// 计算持续时间和比特率int64_t duration = pFormatCtx->duration != AV_NOPTS_VALUE ?av_rescale_q(pFormatCtx->duration, AV_TIME_BASE_Q, {1, 1000}) : -1; // 转换为毫秒int64_t bitrate = pFormatCtx->bit_rate / 1000;// 解析流信息并处理无音频流的情况bool hasAudioStream = false;for (unsigned int i = 0; i < pFormatCtx->nb_streams; ++i) {AVStream *stream = pFormatCtx->streams[i];AVCodecParameters *codecpar = stream->codecpar;if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {LOGD("Video Stream: Codec %s, Resolution %dx%d",avcodec_get_name(codecpar->codec_id),codecpar->width, codecpar->height);} else if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {hasAudioStream = true;// 如果 channel_layout 存在,则使用它;否则提供一个默认值int channels = 2; // 默认立体声音频#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 9, 100)if (codecpar->channel_layout) {channels = av_get_channel_layout_nb_channels(codecpar->channel_layout);}#endifLOGD("Audio Stream: Codec %s, Sample Rate %d Hz, Channels %d",avcodec_get_name(codecpar->codec_id),codecpar->sample_rate,channels);}}if (!hasAudioStream) {LOGD("No audio streams found in the video file.");}char info[1024];snprintf(info, sizeof(info), "Duration: %lld ms, Bitrate: %lld kbps",static_cast<long long>(duration),static_cast<long long>(bitrate));avformat_close_input(&pFormatCtx);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF(info);
}

因为使用的是我自己录制的mp4文件,没有声音的。所以添加了hasAudioStream的判断

  •  修改NativeLib.kt 文件

增加: 

external fun testOpenVideo(path:String): String
  •  方法调用
        val outputDir = getExternalFilesDir(null)val outputFile = File(outputDir, FILENAME)if (!outputFile.exists()) {Log.e(TAG, "File does not exist at path: ${outputFile.absolutePath}")return} else if (!outputFile.canRead()) {Log.e(TAG, "File is not readable at path: ${outputFile.absolutePath}")return}val result = nativeLib.testOpenVideo(outputFile.absolutePath)Log.d(TAG, "-------- $result")

运行成功后

 


上面贴的CMakeLists.txt的内容已经是完整的。下面贴一下ffmpeglib.cpp, NativeLib.kt 和 MainActivity.kt 完整代码。

ffmpeglib.cpp

#include <jni.h>
#include <string>
#include <android/log.h>extern "C" {
#include "ffmpeg/include/libavformat/avformat.h"
}#define LOG_TAG "NativeLib"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)extern "C" JNIEXPORT jstring JNICALL
Java_com_bob_ffmpegdemo_NativeLib_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from FFmpeg";return env->NewStringUTF(hello.c_str());
}extern "C" JNIEXPORT void JNICALL
Java_com_bob_ffmpegdemo_NativeLib_initFfmpeg(JNIEnv *env, jobject /* this */) {// 初始化 FFmpegavformat_network_init();// 打印 FFmpeg 版本信息到日志const char *version = avformat_configuration();LOGD("FFmpeg version: %s", version);
}extern "C" JNIEXPORT jstring JNICALL
Java_com_bob_ffmpegdemo_NativeLib_testOpenVideo(JNIEnv *env, jobject /* this */, jstring filePath) {const char *path = env->GetStringUTFChars(filePath, NULL);// 添加 'file://' 前缀以确保正确解析路径std::string full_path = "file://" + std::string(path);LOGD("Attempting to open video file: %s", full_path.c_str());AVFormatContext *pFormatCtx = nullptr;int ret = avformat_open_input(&pFormatCtx, full_path.c_str(), NULL, NULL);if (ret < 0) {char errbuf[AV_ERROR_MAX_STRING_SIZE];av_strerror(ret, errbuf, sizeof(errbuf));LOGE("Failed to open video file: %s", errbuf);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF("Failed to open video file.");}if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {LOGE("Failed to retrieve stream information.");avformat_close_input(&pFormatCtx);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF("Failed to retrieve stream information.");}// 使用正确的函数名 av_dump_formatav_dump_format(pFormatCtx, 0, full_path.c_str(), 0); // 打印格式信息到标准输出// 计算持续时间和比特率int64_t duration = pFormatCtx->duration != AV_NOPTS_VALUE ?av_rescale_q(pFormatCtx->duration, AV_TIME_BASE_Q, {1, 1000}) : -1; // 转换为毫秒int64_t bitrate = pFormatCtx->bit_rate / 1000;// 解析流信息并处理无音频流的情况bool hasAudioStream = false;for (unsigned int i = 0; i < pFormatCtx->nb_streams; ++i) {AVStream *stream = pFormatCtx->streams[i];AVCodecParameters *codecpar = stream->codecpar;if (codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {LOGD("Video Stream: Codec %s, Resolution %dx%d",avcodec_get_name(codecpar->codec_id),codecpar->width, codecpar->height);} else if (codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {hasAudioStream = true;// 如果 channel_layout 存在,则使用它;否则提供一个默认值int channels = 2; // 默认立体声音频#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 9, 100)if (codecpar->channel_layout) {channels = av_get_channel_layout_nb_channels(codecpar->channel_layout);}#endifLOGD("Audio Stream: Codec %s, Sample Rate %d Hz, Channels %d",avcodec_get_name(codecpar->codec_id),codecpar->sample_rate,channels);}}if (!hasAudioStream) {LOGD("No audio streams found in the video file.");}char info[1024];snprintf(info, sizeof(info), "Duration: %lld ms, Bitrate: %lld kbps",static_cast<long long>(duration),static_cast<long long>(bitrate));avformat_close_input(&pFormatCtx);env->ReleaseStringUTFChars(filePath, path);return env->NewStringUTF(info);
}

NativeLib.kt

package com.bob.ffmpegdemoclass NativeLib {/*** A native method that is implemented by the 'ffmpglib' native library,* which is packaged with this application.*/external fun stringFromJNI(): Stringexternal fun initFfmpeg()external fun testOpenVideo(path:String): Stringcompanion object {// Used to load the 'ffmpeglib' library on application startup.init {System.loadLibrary("ffmpeglib")}}
}

 MainActivity.kt

package com.bob.ffmpegdemoimport android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.bob.ffmpegdemo.databinding.ActivityMainBinding
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStreamclass MainActivity : AppCompatActivity() {companion object {const val FILENAME = "abc.mp4"const val TAG = "TAG"}private val binding: ActivityMainBinding by lazy {ActivityMainBinding.inflate(layoutInflater)}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(binding.root)ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)insets}copyAssetToFile()}private fun copyAssetToFile() {val dir = getExternalFilesDir(null)// Step 1: Create a file object in that directoryval outFile = File(dir, FILENAME)// Step 2: Copy the asset file to the external files directorytry {val `in`: InputStream = assets.open(FILENAME)val out: OutputStream = FileOutputStream(outFile)val buffer = ByteArray(1024)var read: Intwhile ((`in`.read(buffer).also { read = it }) != -1) {out.write(buffer, 0, read)}`in`.close()out.flush()out.close()Log.d(TAG, "Successfully copied $FILENAME to external files directory.")} catch (e: IOException) {Log.e(TAG, "Failed to copy asset file: " + e.message)}}override fun onResume() {super.onResume()testFfmpeg()}private fun testFfmpeg() {val nativeLib = NativeLib()Log.d(TAG, "-------- ${nativeLib.stringFromJNI()}")nativeLib.initFfmpeg()val outputDir = getExternalFilesDir(null)val outputFile = File(outputDir, FILENAME)if (!outputFile.exists()) {Log.e(TAG, "File does not exist at path: ${outputFile.absolutePath}")return} else if (!outputFile.canRead()) {Log.e(TAG, "File is not readable at path: ${outputFile.absolutePath}")return}val result = nativeLib.testOpenVideo(outputFile.absolutePath)Log.d(TAG, "-------- $result")}
}

总结

以上就是今天要讲的内容。

http://www.mmbaike.com/news/93612.html

相关文章:

  • wordpress xml文件分割器枣庄网络推广seo
  • 政府门户网站建设对策建议外包接单平台
  • 云网站开发百度文库官网首页
  • 个人简历word免费模板seo搜论坛
  • 辽宁建设厅查询网站首页武汉seo 网络推广
  • 郑州企业网站优化怎样推广app别人才愿意下载
  • 网站开发 net百度指数关键词工具
  • ui设计包括哪些关键词排名关键词优化
  • 建瓯市建设局网站中国足球世界排名
  • 台州市建设厅网站2022年度最火关键词
  • 深圳网站备案时间seo如何优化关键词排名
  • 响应式网站代码排名seo怎么样
  • 怎么做联盟网站关键词全网搜索
  • 大型企业网络建设方案自动app优化官网
  • 网站开发语言查询 蔡学镛seo优化是怎么优化的
  • 许昌市网站建设各大搜索引擎入口
  • 石家庄网站优化推广适合seo优化的网站
  • 响应式网站开发周期吉安seo
  • 云程环境建设集团网站石家庄seo
  • 大庆 网站建设精准客户截流软件
  • 微信小程序推广引流怎么做seo内链优化
  • 机wordpressseo技术服务外包
  • 网站gzip压缩备案查询官网
  • 红色 网站配色网站优化怎么做
  • 产品宣传册设计网站建设google浏览器官网入口
  • 国家企业信用信息没有网站怎么做怎么提高seo关键词排名
  • 安徽建设工程信息网新网站哪儿登陆网站推广计划书范文500字
  • 南宁中小企业网站制作百度快速收录办法
  • 火影忍者网页设计素材大地seo
  • 我有服务器和模板怎么做网站国外免费建站网站