目前,对于边录制视频,边要显示时间戳的需求,都是通过用对应字符的bitmap图片的yuv数据,来替换每一帧yuv数据的像素点来实现的。这样做的坏处显而易见,这个时间戳数据,是硬生生的印在每一帧数据上的,无法剥离。不能在播放的时候,由用户来控制显不显示。不能动态的配置时间戳字体颜色、大小等样式。

要想解决这个问题,可以用给视频配置对应的字幕来实现。当然,如果一边录一边生成一个*.srt外挂字幕文件,也可以达到目的。不过外挂字幕,终归是要多生成一个文件,让人感觉到不爽。

最好的解决办法,就是边录边写内嵌软字幕。不过现在给视频加字幕,都是在视频录制完后,通过ffmpeg或mp4box来将字幕文件里的字幕打入到mp4里去的。边录边写字幕,这个还没有人做过,网上也没有任何资料。为了解决这个问题,本人参考了ffmpeg、mp4box、vlc源代码,以及用到了mp4info、mediainfo等软件来分析。

要想给视频加上字幕,就必须先了解mp4格式。在mp4里,每一类型的数据,集中在一块,称为一个轨道track。比如最常见的视频轨和音频轨,当然还有我们关心的字幕轨。一个正常的mp4里面的结构如下图所示:

在这个图里面,一共有三个track,前两个为音视频track,最后一个,可以从展开的box里面看到,它为tx3g,也即字幕轨。

用mp4box -info *.mp4来查看,也可以看到mp4里面的大致数据结构:

* Movie Info *
        Timescale 1000 - 3 tracks
        Computed Duration 00:00:17.262 - Indicated Duration 00:00:17.252
        Fragmented File: no
        File suitable for progressive download (moov before mdat)
        File Brand mp42 - version 0
                Compatible brands: isom mp42
        Created: GMT Wed May 15 09:55:46 2019
        Modified: GMT Wed May 15 09:55:46 2019

File has no MPEG4 IOD/OD

Track # 1 Info - TrackID 1 - TimeScale 90000
Media Duration 00:00:17.207 - Indicated Duration 00:00:17.176
Media Info: Language "Undetermined (und)" - Type "vide:avc1" - 513 samples
Visual Track layout: x=0 y=0 width=1920 height=1088
MPEG-4 Config: Visual Stream - ObjectTypeIndication 0x21
AVC/H264 Video - Visual Size 1920 x 1088
        AVC Info: 1 SPS - 1 PPS - Profile Baseline @ Level 4.1
        NAL Unit length bits: 32
        Chroma format YUV 4:2:0 - Luma bit depth 8 - chroma bit depth 8
        SPS#1 hash: C7866EA651F1014BB3FE916BCC6CF22764001970
        PPS#1 hash: 7F4E64F60527715F38B21D7814E9A094754DBFF2
Self-synchronized
        RFC6381 Codec Parameters: avc1.42C029
        Average GOP length: 32 samples

Track # 2 Info - TrackID 2 - TimeScale 44100
Media Duration 00:00:17.262 - Indicated Duration 00:00:17.252
Media Info: Language "Undetermined (und)" - Type "soun:mp4a" - 743 samples
MPEG-4 Config: Audio Stream - ObjectTypeIndication 0x40
MPEG-4 Audio AAC LC - 1 Channel(s) - SampleRate 44100
Synchronized on stream 1
        RFC6381 Codec Parameters: mp4a.40.2
        All samples are sync

Track # 3 Info - TrackID 3 - TimeScale 1000000
Media Duration 00:00:17.000 - Indicated Duration 00:00:17.000
Media Info: Language "Undetermined (und)" - Type "sbtl:tx3g" - 17 samples
Unknown Text Stream
 Size 0 x 0 - Translation X=0 Y=0 - Layer 0
        RFC6381 Codec Parameters: tx3g
Alternate Group ID 3
        All samples are sync

这里可以看第trackId 为3的这个track,是个text stream流,也即这个mp4文件里,包含了一个字幕流。

如果我们要让我们的录制的mp4里包含字幕流,那么必须我们在录制mp4的时候,必须往里面写入一个字幕轨。   本人用到的android工程是android6.0,不过在mp4模块,无论是6.0还是9.0,无论是展迅还是高通平台,代码逻辑都是一样的。

android里,在录制视频的时候,会给视频添加两个源source,一个是audio source,一个是camera source, 这个可以从frameworks\av\media\libmediaplayerservice\StagefrightRecorder.cpp文件里的setupAudioEncoder和setupMPEG4orWEBMRecording函数里看到,添加音视频流是writer->addSource。

其中,音频流对应的文件是frameworks\av\media\libstagefright\AudioSource.cpp,视频流对应的文件是frameworks\av\media\libstagefright\CameraSource.cpp。

当配置好音视频源后,在对应的frameworks\av\media\libstagefright\MPEG4Writer.cpp文件里的MPEG4Writer::Track::threadEntry()里,通过while (!mDone && (err = mSource->read(&buffer)) == OK),会源源不断的从mic和摄像头里,获取音视频数据。然后将获取到的数据,通过mChunkSamples.push_back(copy),将它们放到一个ChunkSamples列表里。当获取到的chunk达到一定数目后,再通过writeChunkToFile,将它写入到mp4里去。

从这个流程来看,我们要加字幕流的话,显然也需要加上一个字幕源加入到这个录制逻辑里去。我们的字幕源,我暂且叫它为SubtitleSource,它不同于音视频源,它的数据,不是从mic或摄像头这些硬件里采集来的。它只需要,每隔一秒钟,就采集一次当前的时间,然后将它传给mSource->read(&buffer),就可以了。当然这个源里的数据,要严格按照mp4的字幕流格式来排列,否则显示不了。

同时,我们不仅仅要添加这个源,还需要针对mp4的字幕轨,新建它特有的box。比如Sthd、Nmhd、Edts、Elst、stsd等box,还需要配置字幕的字体样式。

还有getFourCCForMime这个函数也要作对应的修改,原始的这个函数,只对audio和video的mime type做了处理,我们还需要加上对text类似的处理。 status_t MPEG4Writer::addSource(const sp<MediaSource> &source) 这个函数里,要将if (mTracks.size() >= 2)改成if (mTracks.size() >= 3)。

基本的逻辑大致就是这样,具体的修改后的代码,我会上传到我的博客资源里,有兴趣的可以自己下载下来。

android 边录制视频边写软字幕相关推荐

  1. Android MediaRecorder录制视频详细步骤

    使用MediaRecorder能够编写从设备麦克风与相机捕获音视频,保存音频并(使用MediaPlayer)进行播放的应用. 1.添加权限: <uses-permission android:n ...

  2. 使用FFmpeg命令给视频文件添加软字幕并解决播放器播放没有出现字幕的问题

    添加软字幕这个过程不需要重新编解码,速度非常快.首先我们得准备各种格式的字幕文件,得到方法可以参考文章:<使用Arctime生成各种格式的字幕文件> 给mkv文件添加srt格式的软字幕: ...

  3. android 横屏录制视频,MediaRecorder怎么在竖屏的时候录像结果是横屏录的结果

    public class VideoActivity extends Activity implements SurfaceHolder.Callback { private Button start ...

  4. android 录像 视频大小,Android相机 – 录制视频时预览放大

    我一直试图弄清楚一段时间,但由于某种原因,当我开始使用相机录制视频时,预览放大.我从以下示例中获取以下代码: @Override public void surfaceChanged(SurfaceH ...

  5. android 横屏录制视频,安卓手机如何录制屏幕视频?一招结束录屏的烦恼

    随着手机功能的越来越强大,大大小小的事情都可以在手机上完成,导致我们的生活的吃喝玩乐都用到手机,那么我们有时会在手机上刷到一些好玩的视频,想把它保存下载,但由于无法下载,所以我们就想了各种办法,最后采 ...

  6. Android MediaRecorder录制视频音量小问题解决 (音视频转码合成)

    之前写得太乱,回头看看感觉自己都有点看不懂,重新写下. 在android上需要做一个录像留言功能,需要生成MP4或者waw格式视频.但是使用MediaRecorder录制出的MP4视频格式音量太小,几 ...

  7. Android端录制视频,.NET实时播放

    先列关键词:Android录制.SOCKET转发..NET实时播放,有兴趣的请往下看. 这是一个大工程,兜兜转转,花了不少时间,千真万确,玩成功了. 这是一个小工程,和QQ视频聊天比起来还很low,真 ...

  8. android倒计时录制视频下载,android录制视屏(预览,倒计时)

    android用mediarecord录制视屏,可以设置视屏格式,大小,还有拍摄前预览,倒计时功能要自己用hander做. 1,CameraPreview.java //预览class public ...

  9. Android MediaRecorder录制视频提示start failed的解决办法

    转自https://blog.csdn.net/w815878564/article/details/49247411 今天测试MediaRecorder录制功能的时候出现一个蛋疼的BUG,按照官方提 ...

最新文章

  1. redis设置主从复制-slave Replication--解决报错:(error) READONLY You can't write against a read only slave.
  2. python伪造邮件发件地址_python写一个邮箱伪造脚本
  3. linux串口并行读取,请教linux串口问题!read读取时buf里只读取到8的倍数?
  4. 云原生 DevOps,模型化应用交付能力很重要
  5. 在IDEA中设置Java的堆大小
  6. FreeMarker 基础语法教程
  7. 整理cin.getline与getline函数
  8. HTML学习基础教程
  9. 深度学习框架PyTorch:入门与实践 学习(二)
  10. 计算机学科 集体备课记录,信息技术学科组集体备课活动记录
  11. python下利用百度图像识别接口识别超过十万种物品和场景
  12. 优秀项目经理应具备的素质和能力
  13. Python爬取疫情中高风险地区名单
  14. 软件测试基本流程【车机测试】
  15. 什么是GPS,GPS技术主要有哪些特点?
  16. 一款高颜值的词云包让我拍案叫绝
  17. 【OR】线性规划(2):极方向
  18. dubbo中文官网地址
  19. 计算机排版打字操作,五笔字型与计算机排版培训教程2版 第9章 打字与排版的首选—Word 2007.ppt...
  20. php7.2 webshell,phpStudy后门分析

热门文章

  1. c 语言循环嵌套的例子,C 语言——嵌套循环例子
  2. [ MESH ] MESH功能初步学习(基于802.11s)
  3. 英语流利说:模拟每个人学母语的初心
  4. eclipse快捷键(定位函数,查找类,查找方法)
  5. Linux配置java_home
  6. faiss python安装_Faiss安装
  7. linux创建共享目录
  8. 文本特征提取之词袋模型
  9. mock功能-了解mock的作用及使用场景
  10. SpringBoot+Mybatis(01)