Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
Y
yzg-util
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
YZG
yzg-util
Commits
047d69fc
Commit
047d69fc
authored
Jul 13, 2020
by
yanzg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
视频转换
parent
81c26d88
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
121 additions
and
61 deletions
+121
-61
StringHelper.java
...c/main/java/com/yanzuoguang/util/helper/StringHelper.java
+10
-0
pom.xml
yzg-util-image/pom.xml
+10
-3
MediaHelper.java
...image/src/main/java/com/yanzuoguang/util/MediaHelper.java
+50
-34
MediaParameter.java
...ge/src/main/java/com/yanzuoguang/util/MediaParameter.java
+50
-22
TestMediaHelper.java
yzg-util-image/src/test/java/helper/TestMediaHelper.java
+1
-2
No files found.
yzg-util-base/src/main/java/com/yanzuoguang/util/helper/StringHelper.java
View file @
047d69fc
...
...
@@ -173,6 +173,16 @@ public class StringHelper {
return
getFirstRun
(
0.0
,
0.0
,
froms
);
}
/**
* 传入很多整形,获取第一个非0的值,至少需要两个参数
*
* @param froms 参数列表
* @return 第一个非0值
*/
public
static
Float
getFirst
(
Float
...
froms
)
{
return
getFirstRun
(
0.0f
,
0.0f
,
froms
);
}
/**
* 获取第一个非空值
*
...
...
yzg-util-image/pom.xml
View file @
047d69fc
...
...
@@ -21,15 +21,22 @@
<dependency>
<groupId>
org.bytedeco
</groupId>
<artifactId>
javacv
</artifactId>
<version>
1.
4
.3
</version>
<version>
1.
5
.3
</version>
</dependency>
<!--<dependency>-->
<!--<groupId>org.bytedeco.javacpp-presets</groupId>-->
<!--<artifactId>ffmpeg-platform</artifactId>-->
<!--<version>4.0.2-1.4.3</version>-->
<!--</dependency>-->
<dependency>
<groupId>
org.bytedeco
.javacpp-presets
</groupId>
<groupId>
org.bytedeco
</groupId>
<artifactId>
ffmpeg-platform
</artifactId>
<version>
4.
0.2-1.4
.3
</version>
<version>
4.
2.2-1.5
.3
</version>
</dependency>
<dependency>
<groupId>
net.coobird
</groupId>
<artifactId>
thumbnailator
</artifactId>
...
...
yzg-util-image/src/main/java/com/yanzuoguang/util/MediaHelper.java
View file @
047d69fc
package
com
.
yanzuoguang
.
util
;
import
com.yanzuoguang.util.log.Log
;
import
org.bytedeco.javacpp.avcodec
;
import
org.bytedeco.javacpp.opencv_core
;
import
org.bytedeco.ffmpeg.avcodec.AVPacket
;
import
org.bytedeco.javacv.*
;
import
org.bytedeco.opencv.global.opencv_core
;
import
org.bytedeco.opencv.opencv_core.IplImage
;
import
javax.imageio.ImageIO
;
import
java.awt.image.BufferedImage
;
...
...
@@ -13,6 +14,7 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.List
;
/**
* 视频帮助类
* <p>
...
...
@@ -67,23 +69,12 @@ public class MediaHelper extends ImageHelper {
* @param parameter 转码后的参数,在转码完成后该参数值会被改变
*/
public
static
void
convertVideo
(
String
fromFile
,
String
toFile
,
MediaParameter
parameter
)
throws
IOException
{
initFile
(
fromFile
,
toFile
);
// 视频压缩参数初始化
if
(
parameter
==
null
)
{
parameter
=
new
MediaParameter
();
}
parameter
.
check
();
// 源文件判断
File
source
=
new
File
(
fromFile
);
if
(!
source
.
exists
())
{
throw
new
RuntimeException
(
"视频转码压缩时不存在"
);
}
File
target
=
new
File
(
toFile
);
if
(!
target
.
getParentFile
().
exists
())
{
target
.
getParentFile
().
mkdirs
();
}
if
(
target
.
exists
())
{
target
.
delete
();
}
FFmpegFrameGrabber
grabber
=
new
FFmpegFrameGrabber
(
fromFile
);
try
{
...
...
@@ -98,22 +89,32 @@ public class MediaHelper extends ImageHelper {
FFmpegFrameRecorder
recorder
=
new
FFmpegFrameRecorder
(
toFile
,
parameter
.
getVideoWidthFinally
(),
parameter
.
getVideoHeightFinally
()
parameter
.
getVideoHeightFinally
(),
grabber
.
getAudioChannels
()
);
parameter
.
init
(
grabber
,
recorder
);
try
{
// 转码没有图像
if
(
Frame
)
{
// 开始转换
// recorder.start(grabber.getFormatContext());
recorder
.
start
();
Frame
frame
;
while
((
frame
=
grabber
.
grabFrame
(
true
,
true
,
true
,
false
))
!=
null
)
{
recorder
.
record
(
frame
);
while
((
frame
=
grabber
.
grab
())
!=
null
)
{
// 从视频帧中获取图片
if
(
frame
.
image
!=
null
)
{
recorder
.
record
(
frame
);
}
// 音频帧写入输出流
if
(
frame
.
samples
!=
null
)
{
recorder
.
record
(
frame
);
}
}
}
else
{
// 开始转换
recorder
.
start
(
grabber
.
getFormatContext
());
avcodec
.
AVPacket
packet
;
AVPacket
packet
;
while
((
packet
=
grabber
.
grabPacket
())
!=
null
)
{
recorder
.
recordPacket
(
packet
);
}
...
...
@@ -121,9 +122,8 @@ public class MediaHelper extends ImageHelper {
}
finally
{
// 设置转码后的视频角度
recorder
.
setMetadata
(
MediaParameter
.
ROTATE
,
String
.
valueOf
(
parameter
.
getVideoRotateFinally
()));
recorder
.
release
();
recorder
.
stop
();
recorder
.
release
();
recorder
.
close
();
}
...
...
@@ -136,6 +136,21 @@ public class MediaHelper extends ImageHelper {
}
private
static
void
initFile
(
String
fromFile
,
String
toFile
)
{
// 源文件判断
File
source
=
new
File
(
fromFile
);
if
(!
source
.
exists
())
{
throw
new
RuntimeException
(
"视频转码压缩时不存在"
);
}
File
target
=
new
File
(
toFile
);
if
(!
target
.
getParentFile
().
exists
())
{
target
.
getParentFile
().
mkdirs
();
}
if
(
target
.
exists
())
{
target
.
delete
();
}
}
/**
* 从视频文件中获取第一张图片
*
...
...
@@ -166,26 +181,27 @@ public class MediaHelper extends ImageHelper {
if
(
file2
.
exists
())
{
throw
new
RuntimeException
(
"视频文件"
+
filePath
+
"不存在"
);
}
FFmpegFrameGrabber
ff
=
new
FFmpegFrameGrabber
(
filePath
);
FFmpegFrameGrabber
grabber
=
new
FFmpegFrameGrabber
(
filePath
);
MediaParameter
parameter
=
new
MediaParameter
();
try
{
// 打开视频
ff
.
start
();
// 获取视频的角度
String
rotate
=
ff
.
getVideoMetadata
(
MediaParameter
.
ROTATE
);
grabber
.
start
();
parameter
.
init
(
grabber
);
double
rotate
=
parameter
.
getVideoRotateFinally
(
);
// 整个视频的长度
int
ffLength
=
ff
.
getLengthInFrames
();
int
ffLength
=
grabber
.
getLengthInFrames
();
// 取得能够取得的帧数
index
=
Math
.
min
(
ffLength
,
index
);
for
(
int
i
=
0
;
i
<=
ffLength
;
i
++)
{
Frame
f
=
ff
.
grabImage
();
Frame
f
=
grabber
.
grabImage
();
if
(
i
==
index
)
{
// 判断是否需要旋转
if
(
null
!=
rotate
&&
rotate
.
length
()
>
1
)
{
if
(
rotate
!=
0
)
{
// 旋转角度,防止图像不正确
OpenCVFrameConverter
.
ToIplImage
converter
=
new
OpenCVFrameConverter
.
ToIplImage
();
opencv_core
.
IplImage
src
=
converter
.
convert
(
f
);
f
=
converter
.
convert
(
rotate
(
src
,
Integer
.
valueOf
(
rotate
)
));
IplImage
src
=
converter
.
convert
(
f
);
f
=
converter
.
convert
(
rotate
(
src
,
rotate
));
}
doExecuteFrame
(
f
,
toFile
,
type
);
...
...
@@ -193,8 +209,8 @@ public class MediaHelper extends ImageHelper {
}
}
}
finally
{
ff
.
close
();
ff
.
stop
();
grabber
.
close
();
grabber
.
stop
();
}
}
...
...
@@ -205,13 +221,13 @@ public class MediaHelper extends ImageHelper {
* @param angle
* @return
*/
public
static
opencv_core
.
IplImage
rotate
(
opencv_core
.
IplImage
src
,
int
angle
)
{
opencv_core
.
IplImage
img
=
opencv_core
.
IplImage
.
create
(
public
static
IplImage
rotate
(
IplImage
src
,
double
angle
)
{
IplImage
img
=
IplImage
.
create
(
src
.
height
(),
src
.
width
(),
src
.
depth
(),
src
.
nChannels
()
);
opencv_core
.
cvTranspose
(
src
,
img
);
opencv_core
.
cvFlip
(
img
,
img
,
angle
);
opencv_core
.
cvFlip
(
img
,
img
,
(
int
)
angle
);
return
img
;
}
...
...
yzg-util-image/src/main/java/com/yanzuoguang/util/MediaParameter.java
View file @
047d69fc
...
...
@@ -4,14 +4,12 @@ import com.yanzuoguang.util.helper.StringHelper;
import
com.yanzuoguang.util.log.Log
;
import
com.yanzuoguang.util.vo.BaseVo
;
import
io.swagger.annotations.ApiModelProperty
;
import
org.bytedeco.javacpp.avcodec
;
import
org.bytedeco.javacpp.avutil
;
import
org.bytedeco.javacv.FFmpegFrameGrabber
;
import
org.bytedeco.javacv.FFmpegFrameRecorder
;
import
static
org
.
bytedeco
.
javacpp
.
avcodec
.
AV_CODEC_ID_NONE
;
import
static
org
.
bytedeco
.
javacpp
.
avutil
.
AV_PIX_FMT_NONE
;
import
static
org
.
bytedeco
.
javacpp
.
avutil
.
AV_SAMPLE_FMT_NONE
;
import
static
org
.
bytedeco
.
ffmpeg
.
global
.
avcodec
.*
;
import
static
org
.
bytedeco
.
ffmpeg
.
global
.
avutil
.*
;
/**
* 压缩视频参数
...
...
@@ -20,9 +18,10 @@ import static org.bytedeco.javacpp.avutil.AV_SAMPLE_FMT_NONE;
*/
public
class
MediaParameter
extends
BaseVo
{
public
static
final
int
VIDEO_CODEC_MP4
=
avcodec
.
AV_CODEC_ID_H264
;
public
static
final
int
VIDEO_CODEC_MP4
=
AV_CODEC_ID_H264
;
public
static
final
String
VIDEO_FORMAT_MP4
=
"mp4"
;
public
static
final
int
VIDEO_FIXED_MP4
=
avutil
.
AV_PIX_FMT_YUV420P
;
public
static
final
int
VIDEO_FIXED_MP4
=
AV_PIX_FMT_YUV420P
;
public
static
final
int
SOUND_CODEC_MP3
=
AV_CODEC_ID_VORBIS
;
public
static
final
String
ROTATE
=
"rotate"
;
/**
...
...
@@ -49,7 +48,7 @@ public class MediaParameter extends BaseVo {
* 音频比特率压缩比,算法为: 最终比特率= Math.max(minAudioBitRate,audioBitRate * audioBitRateZip)
*/
@ApiModelProperty
(
notes
=
"音频比特率压缩比,算法为: 最终比特率= Math.max(minAudioBitRate,audioBitRate * audioBitRateZip)"
)
private
float
audioBitRateZip
=
1
;
private
float
audioBitRateZip
=
0
;
/**
* 视频转码后的格式
*/
...
...
@@ -107,7 +106,7 @@ public class MediaParameter extends BaseVo {
*/
@ApiModelProperty
(
notes
=
"视频宽度高度压缩比,算法为: 最终宽度=Math.max(minVideoWidth,videoWidth * videoSizeZip),"
+
"最终高度:=Math.max(minVideoHeight,videoHeight * videoSizeZip)"
)
private
float
videoSizeZip
=
1
;
private
float
videoSizeZip
=
0
;
/**
* 视频转码的比特率,为0时表示采取原来的值
*/
...
...
@@ -122,7 +121,7 @@ public class MediaParameter extends BaseVo {
* 视频比特率压缩比,算法为: 最终比特率= Math.max(minAudioBitRate,audioBitRate * audioBitRateZip)
*/
@ApiModelProperty
(
notes
=
"视频比特率压缩比,算法为: 最终比特率= Math.max(minAudioBitRate,audioBitRate * audioBitRateZip)"
)
private
float
videoBitRateZip
=
1
;
private
float
videoBitRateZip
=
0
;
/**
...
...
@@ -149,7 +148,7 @@ public class MediaParameter extends BaseVo {
* @return
*/
public
int
getVideoWidthFinally
()
{
return
Math
.
max
(
this
.
minVideoWidth
,
(
int
)
(
this
.
videoWidth
*
this
.
videoSizeZip
)
);
return
getWidthHeightFinally
(
true
);
}
/**
...
...
@@ -158,7 +157,15 @@ public class MediaParameter extends BaseVo {
* @return
*/
public
int
getVideoHeightFinally
()
{
return
Math
.
max
(
this
.
minVideoHeight
,
(
int
)
(
this
.
videoHeight
*
this
.
videoSizeZip
));
return
getWidthHeightFinally
(
false
);
}
private
int
getWidthHeightFinally
(
boolean
width
)
{
if
(
width
)
{
return
Math
.
max
(
this
.
minVideoWidth
,
(
int
)
(
this
.
videoWidth
*
this
.
videoSizeZip
));
}
else
{
return
Math
.
max
(
this
.
minVideoHeight
,
(
int
)
(
this
.
videoHeight
*
this
.
videoSizeZip
));
}
}
/**
...
...
@@ -174,6 +181,9 @@ public class MediaParameter extends BaseVo {
* 检查参数
*/
public
void
check
()
{
this
.
audioBitRateZip
=
StringHelper
.
getFirst
(
this
.
audioBitRateZip
,
1
f
);
this
.
videoSizeZip
=
StringHelper
.
getFirst
(
this
.
videoSizeZip
,
1
f
);
this
.
videoBitRateZip
=
StringHelper
.
getFirst
(
this
.
videoBitRateZip
,
1
f
);
if
(
audioBitRateZip
>
1
)
{
throw
new
RuntimeException
(
"audioBitRateZip请在0~1之间"
);
}
...
...
@@ -208,7 +218,7 @@ public class MediaParameter extends BaseVo {
this
.
videoPixelFormat
=
StringHelper
.
getFirstRun
(
AV_PIX_FMT_NONE
,
AV_PIX_FMT_NONE
,
this
.
videoPixelFormat
,
grabber
.
getPixelFormat
());
// 读取视频属性
this
.
videoRotate
=
StringHelper
.
toDouble
(
grabber
.
getVideoMetadata
(
ROTATE
));
this
.
videoFrameRate
=
StringHelper
.
getFirst
(
this
.
videoFrameRate
,
grabber
.
getFrameRate
());
this
.
videoFrameRate
=
StringHelper
.
getFirst
(
this
.
videoFrameRate
,
grabber
.
get
Video
FrameRate
());
this
.
videoBitRate
=
StringHelper
.
getFirst
(
this
.
videoBitRate
,
grabber
.
getVideoBitrate
());
}
...
...
@@ -218,28 +228,45 @@ public class MediaParameter extends BaseVo {
* @param recorder 需要转码的对象
*/
public
void
init
(
FFmpegFrameGrabber
grabber
,
FFmpegFrameRecorder
recorder
)
{
recorder
.
setTimestamp
(
grabber
.
getTimestamp
());
recorder
.
setFormat
(
grabber
.
getFormat
());
recorder
.
setOptions
(
grabber
.
getOptions
());
recorder
.
setMetadata
(
grabber
.
getMetadata
());
recorder
.
setAudioMetadata
(
grabber
.
getAudioMetadata
());
recorder
.
setVideoMetadata
(
grabber
.
getVideoMetadata
());
recorder
.
setAspectRatio
(
recorder
.
getAspectRatio
());
recorder
.
setAudioOptions
(
recorder
.
getAudioOptions
());
recorder
.
setVideoOptions
(
grabber
.
getVideoOptions
());
// 设置音频比特率
recorder
.
setAudioBitrate
(
this
.
getAudioBitRateFinally
());
// recorder.setAudioCodec(this.audioCodec);
/*
recorder.setAudioCodec(this.audioCodec);
// 设置声道
recorder.setAudioChannels(grabber.getAudioChannels());
// 设置声音质量
recorder.setAudioQuality(recorder.getAudioQuality());
// 设置音频属性
// recorder.setSampleFormat(grabber.getSampleFormat());
// recorder.setSampleRate(grabber.getSampleRate());
recorder.setSampleFormat(grabber.getSampleFormat());
recorder.setSampleRate(grabber.getSampleRate());
/* */
// 视频格式
recorder
.
setFormat
(
this
.
videoFormat
);
// 设置转码视频格式
recorder
.
setVideoCodec
(
this
.
videoCodeC
);
// 设置像素格式
//
recorder.setPixelFormat(this.videoPixelFormat);
recorder
.
setPixelFormat
(
this
.
videoPixelFormat
);
// 设置转码后的视频角度
recorder
.
setMetadata
(
ROTATE
,
String
.
valueOf
(
this
.
getVideoRotateFinally
()));
recorder
.
set
Video
Metadata
(
ROTATE
,
String
.
valueOf
(
this
.
getVideoRotateFinally
()));
// 设置视频比特率
recorder
.
setVideoBitrate
(
StringHelper
.
getFirst
(
this
.
getVideoBitRateFinally
(),
this
.
getAudioBitRateFinally
()));
// 设置帧速率
recorder
.
set
FrameRate
(
grabber
.
getFrameRate
()
);
recorder
.
set
VideoQuality
(
this
.
videoFrameRate
);
// 帧长度
recorder
.
setTimestamp
(
grabber
.
getTimestamp
());
}
...
...
@@ -247,14 +274,15 @@ public class MediaParameter extends BaseVo {
public
void
initZipMp4
()
{
this
.
initMp4
();
// 设置压缩帧
this
.
videoFrameRate
=
15
;
this
.
videoFrameRate
=
StringHelper
.
getFirst
(
this
.
videoFrameRate
,
15
d
)
;
// 设置压缩大小
this
.
videoSizeZip
=
0.5f
;
this
.
videoSizeZip
=
StringHelper
.
getFirst
(
this
.
videoSizeZip
,
0.25f
)
;
// 设置视频压缩率
this
.
videoBitRateZip
=
0.5f
;
this
.
videoBitRateZip
=
StringHelper
.
getFirst
(
this
.
videoBitRateZip
,
0.25f
)
;
}
public
void
initMp4
()
{
this
.
audioCodec
=
SOUND_CODEC_MP3
;
this
.
videoCodeC
=
VIDEO_CODEC_MP4
;
this
.
videoFormat
=
VIDEO_FORMAT_MP4
;
this
.
videoPixelFormat
=
VIDEO_FIXED_MP4
;
...
...
yzg-util-image/src/test/java/helper/TestMediaHelper.java
View file @
047d69fc
...
...
@@ -65,8 +65,7 @@ public class TestMediaHelper {
MediaParameter
parameter
=
new
MediaParameter
();
parameter
.
setVideoSizeZip
(
size
);
parameter
.
setVideoBitRateZip
(
quote
);
// parameter.setVideoFrameRate(15);
MediaHelper
.
convertVideo
(
file
,
toFile
,
parameter
);
MediaHelper
.
convertVideo
Mp4
(
file
,
toFile
,
parameter
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment