Android高仿抖音照片电影功能的实现代码

PhotoMovie (https://github.com/yellowcath/PhotoMovie) 可轻松实现类似抖音、微视、美拍的照片电影功能。

效果如下

滤镜效果

转场效果

使用

首先在项目根目录的build.gradle文件里添加maven库

allprojects {
    repositories {
      ...
      maven { url 'https://www.jitpack.io' }
    }
  }

再在需要用的Module的build.gradle里添加依赖

dependencies {
  compile 'com.github.yellowcath:PhotoMovie:1.5.0'
}

基本用法

可参照 DemoPresenter

//添加图片
    List<PhotoData> photoDataList = new LinkedList<PhotoData>();
    photoDataList.add(new SimplePhotoData(context,photoPath1,PhotoData.STATE_LOCAL));
    ...
    photoDataList.add(new SimplePhotoData(context,photoPathN,PhotoData.STATE_LOCAL));
    //生成图片源
    PhotoSource photoSource = new PhotoSource(photoDataList);
    //生成照片电影(使用预定义的水平转场动画)
    PhotoMovie photoMovie = PhotoMovieFactory.generatePhotoMovie(photoSource, PhotoMovieFactory.PhotoMovieType.HORIZONTAL_TRANS);
    //生成负责绘制电影内容的MovieRenderer
    MovieRenderer movieRenderer = new GLTextureMovieRender(glTextureView);
    /**
     * OR MovieRenderer movieRenderer = new GLSurfaceMovieRenderer(glSurfaceView);
     */
    //照片电影播放器
    PhotoMoviePlayer photoMoviePlayer = new PhotoMoviePlayer(context);
    photoMoviePlayer.setMovieRenderer(mMovieRenderer);
    photoMoviePlayer.setMovieListener(...);
    photoMoviePlayer.setLoop(true);
    photoMoviePlayer.setOnPreparedListener(new PhotoMoviePlayer.OnPreparedListener() {
      @Override
      public void onPreparing(PhotoMoviePlayer moviePlayer, float progress) {
      }

      @Override
      public void onPrepared(PhotoMoviePlayer moviePlayer, int prepared, int total) {
         mPhotoMoviePlayer.start();
      }

      @Override
      public void onError(PhotoMoviePlayer moviePlayer) {
      }
    });
    photoMoviePlayer.prepare();

轻松扩展

PhotoMovie使用模块化的设计,每个部分都可以自定义然后替换,

  • MovieSegment:电影片段,每个电影片段都有特定的时长,在这段时间之内以特定的方式播放图片,例如ScaleSegment会对图片做缩放动画、EndGaussianBlurSegment会对图片做从清晰到模糊的高斯模糊动画
  • PhotoMovie:核心类,代表照片电影本身,由图片源(PhotoSource)和若干电影片段(MovieSegment)组成一个完整的照片电影,图片通过PhotoAllocator分配给MovieSegment
  • MovieLayer:为MovieSegment扩展绘制多层特效的功能,例如SubtitleLayer提供字幕展示
  • IMovieFilter:为整个照片电影提供滤镜
  • MovieRenderer:负责把照片电影渲染到指定的输出界面,例如TextureView(GLTextureMovieRender)、GLSurfaceView(GLSurfaceMovieRenderer)
  • PhotoMoviePlayer:提供类似MediaPlayer的接口,负责播放照片电影,播放进度由IMovieTimer控制

扩展电影类型

目前内置了6种类型,后两种即是抖音的左右切换和上下切换,Thaw和WINDOW仿自美拍

public enum PhotoMovieType {
    THAW, //融雪
    SCALE, //缩放
    SCALE_TRANS, //缩放 & 平移
    WINDOW, //窗扉
    HORIZONTAL_TRANS,//横向平移
    VERTICAL_TRANS//纵向平移
  }

这里以微视的渐变特效为例展示如何扩展

分析得出,渐变特效首先图片居中放置,然后全程做一个微弱的放大动画,后半部分同时透明度变化消失

可见需要两个不同的片段类型

首先创建FitCenterScaleSegment,继承FitCenterSegment,实现单张图片的放大动画

public class FitCenterScaleSegment extends FitCenterSegment {
  /**
   * 缩放动画范围
   */
  private float mScaleFrom;
  private float mScaleTo;

  private float mProgress;

  /**
   * @param duration 片段时长
   * @param scaleFrom 缩放范围
   * @param scaleTo  缩放范围
   */
  public FitCenterScaleSegment(int duration, float scaleFrom, float scaleTo) {
    super(duration);
    mScaleFrom = scaleFrom;
    mScaleTo = scaleTo;
  }

  @Override
  protected void onDataPrepared() {
    super.onDataPrepared();
  }

  @Override
  public void drawFrame(GLESCanvas canvas, float segmentProgress) {
    mProgress = segmentProgress;
    if (!mDataPrepared) {
      return;
    }
    drawBackground(canvas);
    float scale = mScaleFrom + (mScaleTo - mScaleFrom) * mProgress;
    //FitCenterSegment已经具有缩放能力,这里传缩放值即可
    drawContent(canvas, scale);
  }
  //提升这两个函数的访问权限,供转场时使用
    @Override
  public void drawContent(GLESCanvas canvas, float scale) {
    super.drawContent(canvas, scale);
  }

  @Override
  public void drawBackground(GLESCanvas canvas) {
    super.drawBackground(canvas);
  }
}

然后创建转场片段GradientTransferSegment,其父类TransitionSegment同时持有上一个与下一个片段,可以在其基础上实现任意转场功能

public class GradientTransferSegment extends TransitionSegment<FitCenterScaleSegment, FitCenterScaleSegment> {
  /**
   * 缩放动画范围
   */
  private float mPreScaleFrom;
  private float mPreScaleTo;
  private float mNextScaleFrom;
  private float mNextScaleTo;

  public GradientTransferSegment(int duration,
                  float preScaleFrom, float preScaleTo,
                  float nextScaleFrom, float nextScaleTo) {
    mPreScaleFrom = preScaleFrom;
    mPreScaleTo = preScaleTo;
    mNextScaleFrom = nextScaleFrom;
    mNextScaleTo = nextScaleTo;
    setDuration(duration);
  }

  @Override
  protected void onDataPrepared() {

  }

  @Override
  public void drawFrame(GLESCanvas canvas, float segmentProgress) {
    //下一个片段开始放大
    float nextScale = mNextScaleFrom + (mNextScaleTo - mNextScaleFrom) * segmentProgress;
    mNextSegment.drawContent(canvas, nextScale);

    //上一个片段继续放大同时变透明
    float preScale = mPreScaleFrom + (mPreScaleTo - mPreScaleFrom) * segmentProgress;
    float alpha = 1 - segmentProgress;
    mPreSegment.drawBackground(canvas);
    canvas.save();
    canvas.setAlpha(alpha);
    mPreSegment.drawContent(canvas, preScale);
    canvas.restore();
  }

创建照片电影

private static PhotoMovie initGradientPhotoMovie(PhotoSource photoSource) {
    List<MovieSegment> segmentList = new ArrayList<>(photoSource.size());
    for (int i = 0; i < photoSource.size(); i++) {
      if (i == 0) {
        segmentList.add(new FitCenterScaleSegment(1600, 1f, 1.1f));
      } else {
        segmentList.add(new FitCenterScaleSegment(1600, 1.05f, 1.1f));
      }
      if (i < photoSource.size() - 1) {
        segmentList.add(new GradientTransferSegment(800, 1.1f, 1.15f, 1.0f, 1.05f));
      }
    }
    return new PhotoMovie(photoSource, segmentList);
  }

然后将这个PhotoMovie正常播放即可,效果如下

扩展滤镜

目前内置了9个滤镜

public enum FilterType {
  NONE,
  CAMEO,//浮雕
  GRAY,//黑白
  KUWAHARA,//水彩
  SNOW,//飘雪(动态)
  LUT1,
  LUT2,
  LUT3,
  LUT4,
  LUT5,
}

先看IMovieFilter

public interface IMovieFilter {
  void doFilter(PhotoMovie photoMovie,int elapsedTime, FboTexture inputTexture, FboTexture outputTexture);
  void release();
}

外部会提供一个输入纹理,然后由IMovieFilter处理之后绘制到输出纹理上,即实现了滤镜效果

BaseMovieFilter已经实现了基本的输入输出流程,例如要做最基本的黑白滤镜,只需更换FRAGMENT_SHADER即可

public class GrayMovieFilter extends BaseMovieFilter {
  protected static final String FRAGMENT_SHADER = "" +
      "varying highp vec2 textureCoordinate;\n" +
      " \n" +
      "uniform sampler2D inputImageTexture;\n" +
      " \n" +
      "void main()\n" +
      "{\n" +
      "   mediump vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" +
      "   mediump float gray = color.r*0.3+color.g*0.59+color.b*0.11;\n"+
      "   gl_FragColor = vec4(gray,gray,gray,1.0);\n"+
      "}";
  public GrayMovieFilter(){
    super(VERTEX_SHADER,FRAGMENT_SHADER);
  }
}

同时PhotoMovie提供了对Lut滤镜的支持

Lut其实就是Lookup Table(颜色查找表),根据原图的RGB值去相应的lut图里面查找对应转换后的RGB值,从而实现各种滤镜效果

lut(原图)

lut_2.jpg

原图

滤镜效果图

public class LutMovieFilter extends TwoTextureMovieFilter {

  public LutMovieFilter(Bitmap lutBitmap){
    super(loadShaderFromAssets("shader/two_vertex.glsl"),loadShaderFromAssets("shader/lut.glsl"));
    setBitmap(lutBitmap);
  }
}

在LutMovieFilter的构造函数传入上面表格里的lut图,即可实现相应的滤镜效果,前面提到的黑白滤镜也可用这个方式实现

录制功能

GLMovieRecorder提供了将照片电影录制为mp4的功能

可参照 DemoPresenter的saveVideo()函数

GLMovieRecorder recorder = new GLMovieRecorder();
    recorder.configOutput(width, height(), bitrate,frameRate,iFrameInterval, outputPath);
    recorder.setDataSource(movieRenderer);
    recorder.startRecord(new GLMovieRecorder.OnRecordListener() {
      @Override
      public void onRecordFinish(boolean success) {
        ......
      }

      @Override
      public void onRecordProgress(int recordedDuration, int totalDuration) {
        ......
      }
    });

背景音乐

 mPhotoMoviePlayer.setMusic(context, mMusicUri);

PhotoMovie只提供了播放背景音乐的功能,录制完成之后需自行合成,Demo里使用了

VideoProcessor进行合成

 VideoProcessor.mixAudioTrack(context, videPath, audioPath,outputPath, null, null, 0,100, 1f, 1f);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android高仿抖音照片电影功能的实现代码

    PhotoMovie (https://github.com/yellowcath/PhotoMovie) 可轻松实现类似抖音.微视.美拍的照片电影功能. 效果如下 滤镜效果 转场效果 使用 首先在项目根目录的build.gradle文件里添加maven库 allprojects { repositories { ... maven { url 'https://www.jitpack.io' } } } 再在需要用的Module的build.gradle里添加依赖 dependencies {

  • Android 高仿微信支付数字键盘功能

    现在很多app的支付.输入密码功能,都已经开始使用自定义数字键盘,不仅更加方便.其效果着实精致. 下面带着大家学习下,如何高仿微信的数字键盘,可以拿来直接用在自身的项目中. 先看下效果图: 1. 自定义布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  • Android SwipeRefreshLayout仿抖音app静态刷新

    SwipeRefreshLayout的功能就是可以让我们的界面在不动的情况下,下拉直接刷新 废话不多说,效果图奉上: activity_listview布局文件 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/sr1" android:layout_width="match_parent" android:layout_height="match_parent"&

  • Android 仿抖音的评论列表的UI和效果的实现代码

    抖音是一款音乐创意短视频社交软件,是一个专注年轻人的15秒音乐短视频社区.用户可以通过这款软件选择歌曲,拍摄15秒的音乐短视频,形成自己的作品.此App已在Android各大应用商店和APP Store均有上线. 在design包里面 有一个 BottomSheetDialogFragment 这个Fragment,他已经帮我们处理好了手势,所以实现起来很简单.下面是代码: public class ItemListDialogFragment extends BottomSheetDialog

  • Android仿抖音右滑清屏左滑列表功能的实现代码

    概述 ​ 项目中要实现仿抖音直播间滑动清屏,侧滑列表的功能,在此记录下实现过程和踩坑记录希望避免大家走些弯路,也当作自己的一个总结 ​ 首先看下Demo中的效果 ​ 阅读文章需要提前熟悉些事件分发的内容,相信大家都已经了解过了,网上也有很多优秀的文章,这里推荐两篇自己读过印象较深的文章 https://www.jb51.net/article/124249.htm https://www.jb51.net/article/124861.htm 关于这方面的知识,在Android中是再重要不过的了

  • 基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能

    一.项目简介 uni-liveShow是一个基于vue+uni-app技术开发的集小视频/IM聊天/直播等功能于一体的微直播项目.界面仿制抖音|火山小视频/陌陌直播,支持编译到多端(H5.小程序.App端) 且兼容效果一致. 二.效果预览 在H5.小程序.App端测试效果如下:(后续大图均为APP端) 三.使用技术 编码器+技术:HBuilderX + vue/NVue/uniapp/vuex iconfont图标:阿里字体图标库 自定义导航栏 + 底部Tabbar 弹窗组件:uniPop(un

  • Android 高仿微信朋友圈拍照上传功能

    模仿微信朋友圈发布动态,输入文字支持文字多少高度自增,有一个最小输入框高度,输入文字有限制,不过这些都很easy! 1. PhotoPicker的使用 这是一个支持选择多张图片,点击图片放大,图片之间左右滑动互相切换的库,同时支持图片删除的库,效果类似微信. (1) 添加PhotoPicker的架包 (2) 使用 选择图片:安卓6.0以后需要在代码中添加读写sd卡和相机的权限 当然清单文件中也需要添加的 PhotoPicker.builder() .setPhotoCount(maxPhoto)

  • Android仿抖音列表效果

    本文实例为大家分享了Android仿抖音列表效果的具体代码,供大家参考,具体内容如下 当下抖音非常火热,是不是也很心动做一个类似的app吗? 那我们就用RecyclerView实现这个功能吧,关于内存的回收利用就交给RecyclerView就好了. 首先我们先说3个和视频播放暂停相关的接口 public interface OnViewPagerListener { /** * 初始化 */ void onInitComplete(View view); /** * 释放 */ void onP

  • Android仿抖音主页效果实现代码

    写在前面 各位老铁,我又来啦!既然来了,那肯定又来搞事情啦,话不多说,先上图! "抖音"都玩过吧,是不是很好玩,我反正是天天刷,作为一个非著名的Android低级攻城狮,虽然技术菜的一匹,但是也经常刷着刷着会思考:咦?这玩意是用哪个控件做的?这个效果是咋实现的啊?由于本人技术水平有限,所以今天咱就先挑个比较简单的来看看是如何实现的,思考再三,我们就拿抖音首页的这个效果来练练手吧,话不多说,开搞! 一.准备工作 我们先不急着写代码,先对抖音的这种效果做一个简单的分析,首先需要明确的是它是

  • Android自定义videoview仿抖音界面

    本文实例为大家分享了Android自定义videoview仿抖音界面的具体代码,供大家参考,具体内容如下 1.效果图 和抖音的界面效果一模一样,而且可以自定义,需要什么页面,请自己定义 2.自定义videoview package com.example.myapplication20; import android.content.Context; import android.util.AttributeSet; import android.widget.VideoView; /** *

随机推荐