2016-10-22 2 views
1

Я пытаюсь разработать приложение, которое позволяет мне рисовать видео во время его записи, а затем сохранять как запись, так и видео в одном файле mp4 для последующего использования. Кроме того, я хочу использовать библиотеку camera2, особенно то, что мне нужно, чтобы мое приложение запускалось для устройств выше API 21, и я всегда избегаю устаревших библиотек.Как я могу нарисовать видео во время записи его в андроиде, и сохранить видео и рисунок?

Я пробовал много способов сделать это, включая FFmpeg, в котором я поместил наложение TextureView.getBitmap() (из камеры) и растровое изображение, взятое из холста. Это сработало, но поскольку это медленная функция, видео не может захватить достаточное количество кадров (даже не 25 кадров в секунду), и оно работает так быстро. Я хочу, чтобы звук также был включен.

Я думал о библиотеке MediaProjection, но я не уверен, что он может захватить макет, содержащий камеру и рисунок только внутри своего VirtualDisplay, потому что пользователь приложения может добавлять текст также на видео, t хотите, чтобы клавиатура появилась.

Пожалуйста, помогите, это была неделя исследований, и я не нашел ничего, что сработало бы хорошо для меня.

P.S: У меня нет проблем, если после этого немного времени на обработку, после чего пользователь нажимает кнопку «Остановить запись».

EDITED:

Теперь после Ответа Эдди, я использую приложение shadercam рисовать на поверхности камеры, поскольку приложение делает видео рендеринга, и обходной путь, чтобы сделать об оказании моего холста в растровое изображение затем в текстуру GL, однако я не могу сделать это успешно. Мне нужна ваша помощь, ребята, мне нужно закончить приложение: S

Я использую библиотеку shadercam (https://github.com/googlecreativelab/shadercam), и я заменил файл «ExampleRenderer» со следующим кодом:

public class WriteDrawRenderer extends CameraRenderer 
{ 
    private float offsetR = 1f; 
    private float offsetG = 1f; 
    private float offsetB = 1f; 

    private float touchX = 1000000000; 
    private float touchY = 1000000000; 

    private Bitmap textBitmap; 

    private int textureId; 

    private boolean isFirstTime = true; 

    //creates a new canvas that will draw into a bitmap instead of rendering into the screen 
    private Canvas bitmapCanvas; 

    /** 
    * By not modifying anything, our default shaders will be used in the assets folder of shadercam. 
    * 
    * Base all shaders off those, since there are some default uniforms/textures that will 
    * be passed every time for the camera coordinates and texture coordinates 
    */ 
    public WriteDrawRenderer(Context context, SurfaceTexture previewSurface, int width, int height) 
    { 
     super(context, previewSurface, width, height, "touchcolor.frag.glsl", "touchcolor.vert.glsl"); 
     //other setup if need be done here 


    } 

    /** 
    * we override {@link #setUniformsAndAttribs()} and make sure to call the super so we can add 
    * our own uniforms to our shaders here. CameraRenderer handles the rest for us automatically 
    */ 
    @Override 
    protected void setUniformsAndAttribs() 
    { 
     super.setUniformsAndAttribs(); 

     int offsetRLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetR"); 
     int offsetGLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetG"); 
     int offsetBLoc = GLES20.glGetUniformLocation(mCameraShaderProgram, "offsetB"); 

     GLES20.glUniform1f(offsetRLoc, offsetR); 
     GLES20.glUniform1f(offsetGLoc, offsetG); 
     GLES20.glUniform1f(offsetBLoc, offsetB); 

     if (touchX < 1000000000 && touchY < 1000000000) 
     { 
      //creates a Paint object 
      Paint yellowPaint = new Paint(); 
      //makes it yellow 
      yellowPaint.setColor(Color.YELLOW); 
      //sets the anti-aliasing for texts 
      yellowPaint.setAntiAlias(true); 
      yellowPaint.setTextSize(70); 

      if (isFirstTime) 
      { 
       textBitmap = Bitmap.createBitmap(mSurfaceWidth, mSurfaceHeight, Bitmap.Config.ARGB_8888); 
       bitmapCanvas = new Canvas(textBitmap); 
      } 

      bitmapCanvas.drawText("Test Text", touchX, touchY, yellowPaint); 

      if (isFirstTime) 
      { 
       textureId = addTexture(textBitmap, "textBitmap"); 
       isFirstTime = false; 
      } 
      else 
      { 
       updateTexture(textureId, textBitmap); 
      } 

      touchX = 1000000000; 
      touchY = 1000000000; 
     } 
    } 

    /** 
    * take touch points on that textureview and turn them into multipliers for the color channels 
    * of our shader, simple, yet effective way to illustrate how easy it is to integrate app 
    * interaction into our glsl shaders 
    * @param rawX raw x on screen 
    * @param rawY raw y on screen 
    */ 
    public void setTouchPoint(float rawX, float rawY) 
    { 
     this.touchX = rawX; 
     this.touchY = rawY; 
    } 
} 

Пожалуйста, помогите ребята, это был месяц, и я все еще придерживаюсь одного и того же приложения: (и понятия не имею о opengl. Две недели, и я пытаюсь использовать этот проект для своего приложения, и на видео ничего не отображается.

Заранее благодарен

+0

Почему не просто иметь два режима в вашем приложении. Один из них предназначен только для записи, а второй вариант позволяет пользователям добавлять чертеж впоследствии, в основном, видеоредактор с временной шкалой и варианты добавления текстов, растровых изображений и т. Д. Для определенной продолжительности, при завершении вы создаете выходное видео через ffmpeg ... –

+0

Выше комментарий касается эффективности, когда вы сказали, что FFmpeg был слишком медленным, чтобы поймать все кадры, а также обрабатывать наложения чертежей и т. д. –

+0

приложение с двумя режимами не то, что я ищу, спасибо anyways – Unbugiful

ответ

0

грубый набросок, который должен работать, но это совсем немного работы:

  1. Настроить android.media.MediaRecorder для записи видео и аудио
  2. Получите поверхность от MediaRecorder и создать EGLImage от него (https://developer.android.com/reference/android/opengl/EGL14.html#eglCreateWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.lang.Object, int [], int)); вам понадобится весь контекст OpenGL и настройка для этого. Затем вам нужно установить этот EGLImage в качестве цели рендеринга.
  3. Создайте SurfaceTexture внутри этого контекста GL.
  4. Настройка камеры для передачи данных в этом SurfaceTexture
  5. Начало MediaRecorder
  6. На каждый кадр, полученный с камеры, преобразовать рисунок, сделанный пользователем в GL текстуры и композиционный текстуру камеры и рисунок пользователя.
  7. Наконец, вызовите glSwapBuffers отправить скомпонован кадр на видеомагнитофон
+0

Спасибо за ваш ответ, но если вы могли бы продумать подробный больше, я новичок в API-интерфейсе камеры, и особенно в медиа-рекордере, и я абсолютно ничего не знаю о GL, и не смог найти что-то прямое в этом отношении ни здесь, ни в google. Я использую представление текстуры для камеры, так как это рекомендуется Google для моей версии API, будет ли это работать с открытым GL? И какова настройка, которую я должен делать и как это сделать, и как установить MediaRecorder для получения кадров из OpenGL. По крайней мере, мне нужны внешние ссылки, чтобы просветить мой путь. Большое спасибо: D – Unbugiful

+0

Извините, но мне не известны полные образцы для этого, и для меня слишком много кода, чтобы написать простой пример. https://github.com/yulu/ShaderCam охватывает отображение данных камеры на экране; http://stackoverflow.com/questions/16274569/android-video-recording-of-opengl-surface-glsurfaceview имеет ссылки для перехода от GL к записи видео. В промежутке времени вам необходимо собрать чертеж пользователя на данные камеры. –