android 边录制视频边写软字幕
目前,对于边录制视频,边要显示时间戳的需求,都是通过用对应字符的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 边录制视频边写软字幕相关推荐
- Android MediaRecorder录制视频详细步骤
使用MediaRecorder能够编写从设备麦克风与相机捕获音视频,保存音频并(使用MediaPlayer)进行播放的应用. 1.添加权限: <uses-permission android:n ...
- 使用FFmpeg命令给视频文件添加软字幕并解决播放器播放没有出现字幕的问题
添加软字幕这个过程不需要重新编解码,速度非常快.首先我们得准备各种格式的字幕文件,得到方法可以参考文章:<使用Arctime生成各种格式的字幕文件> 给mkv文件添加srt格式的软字幕: ...
- android 横屏录制视频,MediaRecorder怎么在竖屏的时候录像结果是横屏录的结果
public class VideoActivity extends Activity implements SurfaceHolder.Callback { private Button start ...
- android 录像 视频大小,Android相机 – 录制视频时预览放大
我一直试图弄清楚一段时间,但由于某种原因,当我开始使用相机录制视频时,预览放大.我从以下示例中获取以下代码: @Override public void surfaceChanged(SurfaceH ...
- android 横屏录制视频,安卓手机如何录制屏幕视频?一招结束录屏的烦恼
随着手机功能的越来越强大,大大小小的事情都可以在手机上完成,导致我们的生活的吃喝玩乐都用到手机,那么我们有时会在手机上刷到一些好玩的视频,想把它保存下载,但由于无法下载,所以我们就想了各种办法,最后采 ...
- Android MediaRecorder录制视频音量小问题解决 (音视频转码合成)
之前写得太乱,回头看看感觉自己都有点看不懂,重新写下. 在android上需要做一个录像留言功能,需要生成MP4或者waw格式视频.但是使用MediaRecorder录制出的MP4视频格式音量太小,几 ...
- Android端录制视频,.NET实时播放
先列关键词:Android录制.SOCKET转发..NET实时播放,有兴趣的请往下看. 这是一个大工程,兜兜转转,花了不少时间,千真万确,玩成功了. 这是一个小工程,和QQ视频聊天比起来还很low,真 ...
- android倒计时录制视频下载,android录制视屏(预览,倒计时)
android用mediarecord录制视屏,可以设置视屏格式,大小,还有拍摄前预览,倒计时功能要自己用hander做. 1,CameraPreview.java //预览class public ...
- Android MediaRecorder录制视频提示start failed的解决办法
转自https://blog.csdn.net/w815878564/article/details/49247411 今天测试MediaRecorder录制功能的时候出现一个蛋疼的BUG,按照官方提 ...
最新文章
- redis设置主从复制-slave Replication--解决报错:(error) READONLY You can't write against a read only slave.
- python伪造邮件发件地址_python写一个邮箱伪造脚本
- linux串口并行读取,请教linux串口问题!read读取时buf里只读取到8的倍数?
- 云原生 DevOps,模型化应用交付能力很重要
- 在IDEA中设置Java的堆大小
- FreeMarker 基础语法教程
- 整理cin.getline与getline函数
- HTML学习基础教程
- 深度学习框架PyTorch:入门与实践 学习(二)
- 计算机学科 集体备课记录,信息技术学科组集体备课活动记录
- python下利用百度图像识别接口识别超过十万种物品和场景
- 优秀项目经理应具备的素质和能力
- Python爬取疫情中高风险地区名单
- 软件测试基本流程【车机测试】
- 什么是GPS,GPS技术主要有哪些特点?
- 一款高颜值的词云包让我拍案叫绝
- 【OR】线性规划(2):极方向
- dubbo中文官网地址
- 计算机排版打字操作,五笔字型与计算机排版培训教程2版 第9章 打字与排版的首选—Word 2007.ppt...
- php7.2 webshell,phpStudy后门分析