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

小型网站怎样优化大渝网官网

小型网站怎样优化,大渝网官网,wordpress怎么删除评论源码,价格合理的网站建设文章目录 版权声明前言1.Camera1和Camera2的区别2.为什么选择Camera2#xff1f; 一、应用Camera2MediaPlayer实现拍摄功能引入所需权限构建UI界面的XMLActivity中的代码部分 二、在上述界面录制结束后点击跳转新的界面进行视频播放构建播放界面部分的XMLActivity的代码上述代… 文章目录 版权声明前言1.Camera1和Camera2的区别2.为什么选择Camera2 一、应用Camera2MediaPlayer实现拍摄功能引入所需权限构建UI界面的XMLActivity中的代码部分 二、在上述界面录制结束后点击跳转新的界面进行视频播放构建播放界面部分的XMLActivity的代码上述代码中的注释部分为上传功能留白。 三.视频上传功能的实现0.集成Java上传SDK1.application.yml的配置2.Controller层3.Service4.Impl5.工具类在上述Android代码的留白部分加入Okhttp请求 效果 版权声明 1.在视频录制阶段用到的Camera2MediaRecorder技术借鉴了下方博主的文章给出原文链接和版权声明 原文链接 2.在视频播放阶段用到的MediaPlayer技术借鉴了下方博主的文章给出原文连接 原文链接 前言 1.Camera1和Camera2的区别 Camera1和Camera2在多个方面存在显著的区别。 首先从功能角度来看Camera1主要支持一次拍摄一张图片而Camera2则支持一次拍摄多张图片甚至可以是多张格式和尺寸不同的图片。例如使用Camera2你可以同时拍摄一张1440x1080的JPEG图片和一张全尺寸的RAW图片。 其次Camera2提供了更多的手动设置选项如曝光时间、ISO感光度、焦距等这使得用户能够更精细地控制拍摄过程。此外Camera2还支持RAW图像捕获和高速连拍模式等新功能进一步丰富了其拍摄能力。 在性能优化方面Camera2 API支持并行拍摄和预览这使得在同时进行多个操作时表现更好。相比之下Camera1可能在处理并行任务时表现稍显不足。 在检查相机信息方面Camera2引入了CameraCharacteristics实例它专门提供相机信息使得用户可以在不开启相机的前提下检查几乎所有的相机信息。而Camera1则无法在开机相机之前检查详细的相机信息。 从实现逻辑上看Camera1的逻辑是面向Camera对象的所有的行为都是基于这个对象的方法的。如果Camera对象本身存在问题是无法感知的只能在调用方法时抛出异常。而Camera2的逻辑则是面向状态的无论是设备还是会话Session任何状态的改变都可以做出相应的处理。这种逻辑的不同使得Camera2在处理各种情况时更为灵活和高效。 此外Camera2还是现在的多摄像头管理框架可以更好地管理和协调多个摄像头的工作。而Camera1主要是以前的前后摄像头的处理方式。 综上所述Camera2在功能、性能、信息检查以及实现逻辑等方面相较于Camera1有明显的提升和优化更适合现代摄影和多媒体应用的需求。然而具体使用哪种API还需要根据具体的应用场景和需求来决定。 2.为什么选择Camera2 Camera1通常指的是较旧的相机API在功能和性能上相较于Camera2即新的相机API确实有所不足。Camera2提供了更多的手动设置选项、支持并行拍摄和预览、允许在不开启相机的前提下检查相机信息等。此外Camera2还是现在的多摄像头管理框架可以更好地管理和协调多个摄像头的工作。 较新版本的API可能不再支持Camera1中的一些方法。随着技术的不断发展和更新新的API版本往往会引入新的功能和改进同时可能会淘汰或替换旧的方法。 较新版本的API不再支持Camera1中的方法可能会涉及多个方面具体取决于API的更新内容和目标设备的兼容性。以下是一些常见的情况和可能不再支持的方法 相机打开和关闭 openCamera(int)用于打开指定ID的相机。 release()用于释放相机资源。 相机参数设置 getParameters() 和 setParameters(Camera.Parameters)用于获取和设置相机的参数如闪光灯模式、预览大小、图片格式等。 setDisplayOrientation(int)用于设置相机预览的显示方向。 预览和拍摄 setPreviewDisplay(SurfaceHolder)用于设置预览显示的Surface。 startPreview() 和 stopPreview()用于开始和停止预览。 takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback)用于拍摄照片并接收回调。 焦点和缩放 autoFocus(Camera.AutoFocusCallback)用于自动对焦。 startSmoothZoom(int) 和 stopSmoothZoom()用于平滑缩放。 事件监听 setPreviewCallback(Camera.PreviewCallback)用于接收预览帧的回调。 setErrorCallback(Camera.ErrorCallback)用于接收相机错误的回调。 其他 unlock() 和 reconnect()与媒体录制器配合使用用于在录制视频时解锁和重新连接相机。 需要注意的是随着Android版本的更新和Camera2 API的引入许多Camera1的方法被新的API所替代或重新设计。Camera2 API提供了更灵活、更强大的相机功能并支持更多的手动控制和高级特性。因此在开发新应用或更新现有应用时建议迁移到Camera2 API以利用最新的功能和性能优势。 一、应用Camera2MediaPlayer实现拍摄功能 引入所需权限 uses-permission android:nameandroid.permission.INTERNET / !-- 获取网络状态根据网络状态切换进行数据请求网络转换 --uses-permission android:nameandroid.permission.READ_EXTERNAL_STORAGE /!-- 读取外置存储 --uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE /!-- 写外置存储 --uses-permission android:nameandroid.permission.VIBRATE / uses-permission android:nameandroid.permission.RECORD_AUDIO / uses-permission android:nameandroid.permission.CAMERA /uses-feature android:nameandroid.hardware.camera /uses-feature android:nameandroid.hardware.camera.autofocus /构建UI界面的XML ?xml version1.0 encodingutf-8? androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.submit.Camera2TextureViewandroid:idid/textureViewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent/Buttonandroid:idid/btn_finishandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text结束app:layout_constraintTop_toTopOfparentapp:layout_constraintRight_toRightOfparent/Buttonandroid:idid/btn_startandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text开始app:layout_constraintTop_toTopOfparentapp:layout_constraintLeft_toLeftOfparent//androidx.constraintlayout.widget.ConstraintLayoutActivity中的代码部分 package com.example.travelassistant.submit;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat;import android.Manifest; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureResult; import android.hardware.camera2.TotalCaptureResult; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.util.DisplayMetrics; import android.util.Log; import android.util.Size; import android.view.Surface; import android.view.TextureView; import android.view.View; import android.widget.Button;import com.example.travelassistant.R;import java.io.File; import java.io.IOException; import java.util.Arrays;public class Camera2 extends AppCompatActivity {private static final String TAG Camera2.class.getSimpleName();private Button mBtnStatr,mBtnFinish;private TextureView mTextureView;private CameraManager mCameraManager;private CameraDevice mCameraDevice;private CameraCaptureSession mCameraCaptureSession;private CameraDevice.StateCallback mCameraDeviceStateCallback;private CameraCaptureSession.StateCallback mSessionStateCallback;private CameraCaptureSession.CaptureCallback mSessionCaptureCallback;private CaptureRequest.Builder mPreviewCaptureRequest;private CaptureRequest.Builder mRecorderCaptureRequest;private MediaRecorder mMediaRecorder;private String mCurrentSelectCamera;private Handler mChildHandler;SuppressLint(MissingInflatedId)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera2);if(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ! PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.RECORD_AUDIO}, 1);}if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ! PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.CAMERA}, 1);}if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ! PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}mTextureView findViewById(R.id.textureView);mBtnStatr findViewById(R.id.btn_start);mBtnFinish findViewById(R.id.btn_finish);initClickListener();initChildHandler();initTextureViewStateListener();initMediaRecorder();initCameraDeviceStateCallback();initSessionStateCallback();initSessionCaptureCallback();}private void initClickListener(){mBtnStatr.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {config();startRecorder();}});mBtnFinish.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {stopRecorder();}});}/*** 初始化TextureView的纹理生成监听只有纹理生成准备好了。我们才能去进行摄像头的初始化工作让TextureView接收摄像头预览画面*/private void initTextureViewStateListener(){mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {//可以使用纹理initCameraManager();selectCamera();openCamera();}Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {//纹理尺寸变化}Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {//纹理被销毁return false;}Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {//纹理更新}});}/*** 初始化子线程Handler操作Camera2需要一个子线程的Handler*/private void initChildHandler(){HandlerThread handlerThread new HandlerThread(Camera2Demo);handlerThread.start();mChildHandler new Handler(handlerThread.getLooper());}/*** 初始化MediaRecorder*/private void initMediaRecorder(){mMediaRecorder new MediaRecorder();}/*** 配置录制视频相关数据*/private void configMediaRecorder(){File file new File(getExternalCacheDir(),demo.mp4);if (file.exists()){file.delete();}mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置音频来源mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);//设置视频来源mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置输出格式mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频编码格式请注意这里使用默认实际app项目需要考虑兼容问题应该选择AACmMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);//设置视频编码格式请注意这里使用默认实际app项目需要考虑兼容问题应该选择H264mMediaRecorder.setVideoEncodingBitRate(8*1024*1920);//设置比特率 一般是 1*分辨率 到 10*分辨率 之间波动。比特率越大视频越清晰但是视频文件也越大。mMediaRecorder.setVideoFrameRate(30);//设置帧数 选择 30即可 过大帧数也会让视频文件更大当然也会更流畅但是没有多少实际提升。人眼极限也就30帧了。Size size getMatchingSize2();mMediaRecorder.setVideoSize(size.getWidth(),size.getHeight());mMediaRecorder.setOrientationHint(90);Surface surface new Surface(mTextureView.getSurfaceTexture());mMediaRecorder.setPreviewDisplay(surface);mMediaRecorder.setOutputFile(file.getAbsolutePath());try {mMediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();}}/*** 重新配置录制视频时的CameraCaptureSession*/private void config(){try {mCameraCaptureSession.stopRepeating();//停止预览准备切换到录制视频mCameraCaptureSession.close();//关闭预览的会话需要重新创建录制视频的会话mCameraCaptureSession null;} catch (CameraAccessException e) {e.printStackTrace();}configMediaRecorder();Size cameraSize getMatchingSize2();SurfaceTexture surfaceTexture mTextureView.getSurfaceTexture();surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(),cameraSize.getHeight());Surface previewSurface new Surface(surfaceTexture);Surface recorderSurface mMediaRecorder.getSurface();//从获取录制视频需要的Surfacetry {mPreviewCaptureRequest mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);mPreviewCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);mPreviewCaptureRequest.addTarget(previewSurface);mPreviewCaptureRequest.addTarget(recorderSurface);//请注意这里设置了Arrays.asList(previewSurface,recorderSurface) 2个Surface很好理解录制视频也需要有画面预览第一个是预览的Surface第二个是录制视频使用的SurfacemCameraDevice.createCaptureSession(Arrays.asList(previewSurface,recorderSurface),mSessionStateCallback,mChildHandler);} catch (CameraAccessException e) {e.printStackTrace();}}/*** 开始录制视频*/private void startRecorder(){mMediaRecorder.start();}/*** 暂停录制视频暂停后视频文件会自动保存*/private void stopRecorder(){mMediaRecorder.stop();mMediaRecorder.reset();Intent intent new Intent(Camera2.this, PlayVideoActivity.class);startActivity(intent);}/*** 初始化Camera2的相机管理CameraManager用于获取摄像头分辨率摄像头方向摄像头id与打开摄像头的工作*/private void initCameraManager(){mCameraManager (CameraManager)getSystemService(Context.CAMERA_SERVICE);}/*** 选择一颗我们需要使用的摄像头主要是选择使用前摄还是后摄或者是外接摄像头*/private void selectCamera(){if (mCameraManager ! null) {Log.e(TAG, selectCamera: CameraManager is null);}try {String[] cameraIdList mCameraManager.getCameraIdList(); //获取当前设备的全部摄像头id集合if (cameraIdList.length 0){Log.e(TAG, selectCamera: cameraIdList length is 0);}for (String cameraId : cameraIdList){ //遍历所有摄像头CameraCharacteristics characteristics mCameraManager.getCameraCharacteristics(cameraId);//得到当前id的摄像头描述特征Integer facing characteristics.get(CameraCharacteristics.LENS_FACING); //获取摄像头的方向特征信息if (facing CameraCharacteristics.LENS_FACING_BACK){ //这里选择了后摄像头mCurrentSelectCamera cameraId;}}} catch (CameraAccessException e) {e.printStackTrace();}}private void initCameraDeviceStateCallback(){mCameraDeviceStateCallback new CameraDevice.StateCallback() {Overridepublic void onOpened(NonNull CameraDevice camera) {//摄像头被打开try {mCameraDevice camera;Size cameraSize getMatchingSize2();//计算获取需要的摄像头分辨率SurfaceTexture surfaceTexture mTextureView.getSurfaceTexture();//得到纹理surfaceTexture.setDefaultBufferSize(cameraSize.getWidth(),cameraSize.getHeight());Surface previewSurface new Surface(surfaceTexture);mPreviewCaptureRequest mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);mPreviewCaptureRequest.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);mPreviewCaptureRequest.addTarget(previewSurface);mCameraDevice.createCaptureSession(Arrays.asList(previewSurface),mSessionStateCallback,mChildHandler);//创建数据捕获会话用于摄像头画面预览这里需要等待mSessionStateCallback回调} catch (CameraAccessException e) {e.printStackTrace();}}Overridepublic void onDisconnected(NonNull CameraDevice camera) {//摄像头断开}Overridepublic void onError(NonNull CameraDevice camera, int error) {//异常}};}private void initSessionStateCallback(){mSessionStateCallback new CameraCaptureSession.StateCallback() {Overridepublic void onConfigured(NonNull CameraCaptureSession session) {mCameraCaptureSession session;try {//执行重复获取数据请求等于一直获取数据呈现预览画面mSessionCaptureCallback会返回此次操作的信息回调mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequest.build(),mSessionCaptureCallback,mChildHandler);} catch (CameraAccessException e) {e.printStackTrace();}}Overridepublic void onConfigureFailed(NonNull CameraCaptureSession session) {}};}private void initSessionCaptureCallback(){mSessionCaptureCallbacknew CameraCaptureSession.CaptureCallback() {Overridepublic void onCaptureStarted(NonNull CameraCaptureSession session, NonNull CaptureRequest request, long timestamp, long frameNumber) {super.onCaptureStarted(session, request, timestamp, frameNumber);}Overridepublic void onCaptureProgressed(NonNull CameraCaptureSession session, NonNull CaptureRequest request, NonNull CaptureResult partialResult) {super.onCaptureProgressed(session, request, partialResult);}Overridepublic void onCaptureCompleted(NonNull CameraCaptureSession session, NonNull CaptureRequest request, NonNull TotalCaptureResult result) {super.onCaptureCompleted(session, request, result);}Overridepublic void onCaptureFailed(NonNull CameraCaptureSession session, NonNull CaptureRequest request, NonNull CaptureFailure failure) {super.onCaptureFailed(session, request, failure);}};}/*** 打开摄像头这里打开摄像头后我们需要等待mCameraDeviceStateCallback的回调*/SuppressLint(MissingPermission)private void openCamera(){try {mCameraManager.openCamera(mCurrentSelectCamera,mCameraDeviceStateCallback,mChildHandler);} catch (CameraAccessException e) {e.printStackTrace();}}/*** 计算需要的使用的摄像头分辨率* return*/private Size getMatchingSize2(){Size selectSize null;try {CameraCharacteristics cameraCharacteristics mCameraManager.getCameraCharacteristics(mCurrentSelectCamera);StreamConfigurationMap streamConfigurationMap cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);Size[] sizes streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);DisplayMetrics displayMetrics getResources().getDisplayMetrics(); //因为我这里是将预览铺满屏幕,所以直接获取屏幕分辨率int deviceWidth displayMetrics.widthPixels; //屏幕分辨率宽int deviceHeigh displayMetrics.heightPixels; //屏幕分辨率高Log.e(TAG, getMatchingSize2: 屏幕密度宽度deviceWidth);Log.e(TAG, getMatchingSize2: 屏幕密度高度deviceHeigh );/*** 循环40次,让宽度范围从最小逐步增加,找到最符合屏幕宽度的分辨率,* 你要是不放心那就增加循环,肯定会找到一个分辨率,不会出现此方法返回一个null的Size的情况* ,但是循环越大后获取的分辨率就越不匹配*/Integer ssizes.length;selectSizesizes[s-1];} catch (CameraAccessException e) {e.printStackTrace();}Log.e(TAG, getMatchingSize2: 选择的分辨率宽度selectSize.getWidth());Log.e(TAG, getMatchingSize2: 选择的分辨率高度selectSize.getHeight());return selectSize;}}二、在上述界面录制结束后点击跳转新的界面进行视频播放 构建播放界面部分的XML ?xml version1.0 encodingutf-8? LinearLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:orientationverticaltools:context.submit.PlayVideoActivitySurfaceViewandroid:idid/surfaceViewandroid:layout_weight10android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:rotation90/!--水平线性布局--LinearLayoutandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:layout_weight1android:orientationhorizontal!--播放按钮--Buttonandroid:idid/play1android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text播放/!--暂停按钮--Buttonandroid:idid/pause1android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text取消 /!--停止按钮--Buttonandroid:idid/stop1android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_weight1android:text上传 //LinearLayout/LinearLayoutActivity的代码 package com.example.travelassistant.submit;import androidx.appcompat.app.AppCompatActivity;import android.media.AudioManager; import android.media.MediaMetadataRetriever; import android.media.MediaPlayer; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.Toast;import com.example.travelassistant.R; import com.example.travelassistant.utils.AsyncResponse; import com.example.travelassistant.utils.SendRequest;import java.io.File; import java.io.IOException;public class PlayVideoActivity extends AppCompatActivity {private SurfaceView surfaceView;private Button play, pause, stop;private MediaPlayer mediaPlayer;private SurfaceHolder surfaceHolder;private boolean noPlay true;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_play_video);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);play (Button) findViewById(R.id.play1);pause (Button) findViewById(R.id.pause1);stop (Button) findViewById(R.id.stop1);surfaceView (SurfaceView) findViewById(R.id.surfaceView);surfaceHolder surfaceView.getHolder();pause.setEnabled(false);stop.setEnabled(false);/*** 实现播放功能*/play.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {if (noPlay) {play();noPlay false;} else {mediaPlayer.start();}}});/*** 实现取消功能*/pause.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {mediaPlayer.stop();mediaPlayer.release();//返回主页面if (mediaPlayer.isPlaying()) {mediaPlayer.pause();}}});/*** 实现上传功能*/stop.setOnClickListener(new View.OnClickListener(){Overridepublic void onClick(View v) {if (mediaPlayer.isPlaying()) {mediaPlayer.stop();mediaPlayer.release();noPlay true;pause.setEnabled(false);stop.setEnabled(false);}File filenew File(getExternalCacheDir()/demo.mp4);if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}}//这个位置实现视频上传的功能Overridepublic void processFailure() {}});}});}/*** 创建play()方法在该方法中实现视频的播放功能*/public void play() {mediaPlayer new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDisplay(surfaceHolder);try {MediaMetadataRetriever retriever new MediaMetadataRetriever();retriever.setDataSource(getExternalCacheDir()/demo.mp4);String rotation retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);System.out.println(rotation);mediaPlayer.setDataSource(getExternalCacheDir()/demo.mp4);System.out.println(getExternalCacheDir()/demo.mp4);// mediaPlayer.setDataSource(Environment.getExternalStorageDirectory() /DCIM/Camera/video.mp4);mediaPlayer.prepare();} catch (Exception e) {e.printStackTrace();}mediaPlayer.start();pause.setEnabled(true);stop.setEnabled(true);// 为MediaPlayer对象添加完成事件监听器mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {Overridepublic void onCompletion(MediaPlayer mp) {Toast.makeText(PlayVideoActivity.this, 视频播放完毕, Toast.LENGTH_SHORT).show();}});}/*** 当前Activity销毁时停止正在播放的视频并释放MediaPlayer所占用的资源*/Overrideprotected void onDestroy() {super.onDestroy();if (mediaPlayer ! null) {if (mediaPlayer.isPlaying()) {mediaPlayer.stop();}// Activity销毁时停止播放释放资源。不做这个操作即使退出还是能听到视频播放的声音mediaPlayer.release();}} }上述代码中的注释部分为上传功能留白。 三.视频上传功能的实现 在实现视频上传到阿里云VOD功能时有两种思路 1.因为是在Android客户端上实现此功能可以采取客户端的方式可以参考阿里云VOD的开发文档 Android客户端上传文件 2.服务端开发一个上传的接口Android应用Okhttp向服务端发送上传文件的请求 本文主要采取了第二种思路接下来具体介绍如何实现 0.集成Java上传SDK 根据官方文档的提示引入相关依赖 下载Java语言的SDK和Demo将其中的aliyun-java-vod-upload-1.4.15.jar放到模块的resources包下 如下图所示 添加依赖 dependencygroupIdcom.aliyun/groupIdartifactIdaliyun-java-sdk-core/artifactIdversion4.5.1/version/dependencydependencygroupIdcom.aliyun.oss/groupIdartifactIdaliyun-sdk-oss/artifactIdversion3.10.2/version/dependencydependencygroupIdcom.aliyun/groupIdartifactIdaliyun-java-sdk-vod/artifactIdversion2.16.11/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.68.noneautotype/version/dependencydependencygroupIdorg.json/groupIdartifactIdjson/artifactIdversion20170516/version/dependencydependencygroupIdcom.google.code.gson/groupIdartifactIdgson/artifactIdversion2.8.2/version/dependencydependencygroupIdcom.aliyun.vod/groupIdartifactIdupload/artifactIdversion1.4.15/versionscopesystem/scopesystemPath${project.basedir}/src/main/resources/aliyun-java-vod-upload-1.4.15.jar/systemPath/dependency 根据文档文档的提示接下来实现视频文件的上传并将视频中的某一帧作为封面图片 1.application.yml的配置 1和2中要从官网中获取 3表示上传文件 这里要设置的大一点 2.Controller层 //上传视频的同时将视频的某一帧作为封面上传ApiOperation(上传视频并取某帧作为视频的封面)PostMapping(upload)public MapString,Object uploadVideoAndImage(RequestParam(file) MultipartFile multipartFile){String[] stringsvodService.uploadVideoAndImage(multipartFile);HashMapString, Object map new HashMap();map.put(code,0);map.put(message,成功);map.put(data,strings);System.out.println(strings);return map;}3.Service public interface VodService {String[] uploadVideoAndImage(MultipartFile multipartFile);}4.Impl Overridepublic String[] uploadVideoAndImage(MultipartFile multipartFile) {String[] strings new String[3];try {InputStream inputStream multipartFile.getInputStream();final int fifthFrame 10;FFmpegFrameGrabber grabber;grabber new FFmpegFrameGrabber(inputStream);grabber.start();// 视频总帧数int videoLength grabber.getLengthInFrames();Frame frame null;int i 0;while (i videoLength) {// 过滤前5帧,因为前5帧可能是全黑的frame grabber.grabFrame();if ((i fifthFrame) (frame.image ! null)) {break;}i;}Java2DFrameConverter converter new Java2DFrameConverter();// 绘制图片BufferedImage bi converter.getBufferedImage(frame);BufferedImage rotatedImage ImageRotation.rotateImage(bi, 90);grabber.stop();grabber.close();//将图片转换成输入流ByteArrayOutputStream os new ByteArrayOutputStream();ImageIO.write(rotatedImage, png, os);InputStream input new ByteArrayInputStream(os.toByteArray());//绘制完图片后 直接以流的方式将封面图片上传到阿里云String imageType default;UploadImageRequest Imagerequest new UploadImageRequest(LTAI5t6a4Bwa6d21Pd2NRAqo, QLPSNZCYpe6EI70adnq8s9GRgvcYqo, imageType);Imagerequest.setInputStream(input);UploadImageImpl uploadImage new UploadImageImpl();UploadImageResponse Imageresponse uploadImage.upload(Imagerequest);if(Imageresponse.isSuccess()){String imageURL Imageresponse.getImageURL();strings[0]imageURL;String imageId Imageresponse.getImageId();strings[1]imageId;//上传结束后获得图片的url 将图片的Url作为视频的封面图片//获取文件名String originalFilename multipartFile.getOriginalFilename();UploadStreamResponse responsenull;//上传的视频的标题String title originalFilename.substring(0, originalFilename.lastIndexOf(.));UploadStreamRequest request new UploadStreamRequest(ConstantPropertiesUtils.KEY_ID, ConstantPropertiesUtils.KEY_SECRET, title, originalFilename, multipartFile.getInputStream());request.setCoverURL(imageURL);UploadVideoImpl uploader new UploadVideoImpl();response uploader.uploadStream(request);String videoId response.getVideoId();System.out.println(videoId);strings[2]videoId;}} catch (IOException e) {e.printStackTrace();}return strings;}5.工具类 实现照片旋转 package com.ts.oss.util;import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage;public class ImageRotation {public static BufferedImage rotateImage(BufferedImage image, double angle) {int w image.getWidth();int h image.getHeight();// 计算旋转后图像的新边界double sin Math.sin(Math.toRadians(angle));double cos Math.cos(Math.toRadians(angle));int newW (int) Math.floor(Math.abs(w * cos) Math.abs(h * sin));int newH (int) Math.floor(Math.abs(h * cos) Math.abs(w * sin));// 创建一个新的BufferedImage对象用于存储旋转后的图像BufferedImage rotatedImage new BufferedImage(newW, newH, image.getType());// 获取Graphics2D对象以进行绘制Graphics2D g2d rotatedImage.createGraphics();// 设置渲染提示g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 旋转图像AffineTransform at new AffineTransform();at.rotate(Math.toRadians(angle), newW / 2, newH / 2);g2d.setTransform(at);// 绘制旋转后的图像g2d.drawImage(image, (newW - w) / 2, (newH - h) / 2, null);// 释放Graphics2D对象的资源g2d.dispose();return rotatedImage;} } 从配置文件中获取KEY和ID package com.ts.oss.util;import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;Component public class ConstantPropertiesUtils implements InitializingBean {//读取配置文件中的内容Value(${aliyun.oss.file.endpoint})private String endpoint;Value(${aliyun.oss.file.keyid})private String keyId;Value(${aliyun.oss.file.keysecret})private String keySecret;Value(${aliyun.oss.file.bucketname})private String bucketName;//定义公开静态常量 供其他方法使用public static String END_POINT;public static String KEY_ID;public static String KEY_SECRET;public static String BUCKETNAME;Overridepublic void afterPropertiesSet() throws Exception {END_POINTendpoint;KEY_IDkeyId;KEY_SECRETkeySecret;BUCKETNAMEbucketName;} } 在上述Android代码的留白部分加入Okhttp请求 File filenew File(getExternalCacheDir()/demo.mp4); OkHttpClient client new OkHttpClient(); String sendUrlhttp://你的IP地址:你的端口号你的Controller请求路径; MultipartBody.Builder requestBodynew MultipartBody.Builder().setType(MultipartBody.FORM); RequestBody fileBodyRequestBody.create(MediaType.parse(video/*),file); requestBody.addFormDataPart(file, file.getName(),fileBody);Request requestnew Request.Builder().url(sendUrl).post(requestBody.build()).build();//创建http请求client.newCall(request).enqueue(new Callback() {Overridepublic void onFailure(NonNull Call call, NonNull IOException e) {e.printStackTrace();}Overridepublic void onResponse(NonNull Call call, NonNull Response response) throws IOException {String responseBody response.body().string();// 在请求成功时调用回调函数}});效果
http://www.zqtcl.cn/news/800414/

相关文章:

  • 网站建设注意细节问题微信二维码
  • 凡科做的网站提示证书错误网络营销渠道可分为哪几种
  • 南京手机网站制作公司免费设计房屋效果图软件有哪些
  • 定制类网站怎么样做网页设计
  • 企业门户网站建设优势网站登录模版
  • 六盘水建设网站徐州建站平台
  • 昆明有多少做网站的公司公司软文代写
  • 东莞模板网站做一个电子商务网站在哪里做
  • 给别人网站做跳转株洲专业网站排名优化
  • 国外网站空间租用费用网站前端设计图
  • 宜州做网站点点网 xml转wordpress
  • 太原建站方法erp系统好上手吗
  • 网站建设如何实现检索功能河南城乡建设网站
  • 江苏做电缆桥架的公司网站购物网站答辩ppt怎么做
  • 惠州网站建设系统公司公司网站建设公司
  • 做酒类直供网站行吗石家庄桥西网站制作公司
  • 电子商务门户网站的研究与实现漳州做网站多少钱
  • 咖啡网站源码呼和浩特网站建设价位
  • 邯郸哪儿能做网站广州冼村房价多少钱
  • 网站建设开发成本设计素材库
  • wordpress获取站点链接wordpress 滑动验证
  • 怎么把网站上的通栏手机公司网站建设
  • 微山县建设局官方网站wordpress 内容换行
  • 网站选择空间ps个人主页设计
  • 河北网站seo外包网站嵌入百度地图
  • 公司怎么开网站WordPress有哪些工具
  • 一流专业建设网站原平新闻头条最新消息
  • 网站开发文档模板 开源北京保障房建设项目网站
  • 营销型网站分类网站关键词如何快速上首页
  • 帝国和WordPress比较wordpress文章页标题优化