media.sh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #!/bin/bash
  2. Media="$1"
  3. ForceH264="${2:-0}"
  4. Uploader="upload.sh"
  5. M3u8mod="m3u8.sh"
  6. Publish="publish.sh"
  7. BitRadio="1.55"
  8. ForceBitRadio="1.75"
  9. ForceMaxRadio="1.20"
  10. ForceRate="2400000"
  11. MaxSize=5
  12. MaxCheck=10
  13. MaxTime=10
  14. AutoClear=0
  15. QuickMode=1
  16. # Main
  17. if [ -n "${Media}" ] && [ -f "${Media}" ]; then
  18. echo "$ForceH264" |grep -q "^-"
  19. [ "$?" -eq 0 ] && QuickMode=0
  20. ForceH264=`echo "$ForceH264" |grep -o "[0-9]\{1,\}"`
  21. [ -n "$ForceH264" ] || ForceH264=0
  22. echo "media file: '${Media}'."
  23. else
  24. [ -n "${Media}" ] && echo "Not found '${Media}'." || echo "Please input a media file."
  25. exit 1
  26. fi
  27. MediaName=`basename "${Media}" |cut -d'.' -f1 |sed 's/[[:space:]]/_/g'`
  28. ScriptDir=`dirname $0`
  29. CurrentDir=`pwd`
  30. OutPutM3u8="${CurrentDir}/${MediaName}.m3u8"
  31. OutPutM3u8Bak="${CurrentDir}/${MediaName}.m3u8.bak"
  32. OutPutLog="${CurrentDir}/${MediaName}.log"
  33. MediaFolder="${CurrentDir}/${MediaName}.output"
  34. # cache
  35. [ "$QuickMode" == 1 ] && [ -f "${OutPutM3u8Bak}" ] && [ -d "${MediaFolder}" ] || QuickMode=0
  36. if [ "$QuickMode" != 1 ]; then
  37. rm -rf "${OutPutLog}"
  38. rm -rf "${MediaFolder}"
  39. mkdir -p "${MediaFolder}"
  40. else
  41. rm -rf "${OutPutLog}"
  42. fi
  43. ## m3u8
  44. if [ "$QuickMode" != 1 ]; then
  45. BitRate=`ffprobe -v error -show_entries format=bit_rate -of default=noprint_wrappers=1:nokey=1 "${Media}"`
  46. echo "media bitrate: ${BitRate}"
  47. if [ "$ForceH264" -eq 0 ]; then
  48. _ForceH264=`awk 'BEGIN{print '${BitRate}' / ('${ForceBitRadio}' * '${ForceRate}')}' |cut -d'.' -f1`
  49. [ "$_ForceH264" -ne 0 ] && ForceH264=1
  50. fi
  51. if [ "$ForceH264" -ge 2 ]; then
  52. MediaCode=`ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "${Media}" |sort |uniq`
  53. if [ "$MediaCode" != "h264" ]; then
  54. echo "Error: This media file code '${MediaCode}', must 'h264' in this mode."
  55. exit 1
  56. fi
  57. VideoCode="copy"
  58. VideoAddon="-bsf:v h264_mp4toannexb"
  59. [ "$ForceH264" -le 2 ] && VideoTime="2" || VideoTime="$ForceH264"
  60. elif [ "$ForceH264" -eq 1 ]; then
  61. ForceMaxRate=`awk 'BEGIN{print '${ForceRate}' * '${ForceMaxRadio}'}' |cut -d'.' -f1`
  62. ForceBuf=`awk 'BEGIN{print '${ForceRate}' / '${ForceMaxRadio}'}' |cut -d'.' -f1`
  63. VideoAddon="-b:v ${ForceRate} -maxrate ${ForceMaxRate} -bufsize ${ForceBuf}"
  64. VideoCode="h264"
  65. if [ "$BitRate" -gt "3500000" ]; then
  66. BitRadio="${ForceBitRadio}"
  67. fi
  68. BitRate=3000000
  69. echo "media bitrate(new): ${BitRate}"
  70. else
  71. MediaCode=`ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "${Media}" |sort |uniq`
  72. if [ "$MediaCode" == "h264" ]; then
  73. VideoCode="copy"
  74. else
  75. VideoCode="h264"
  76. fi
  77. if [ "$VideoCode" == "copy" ]; then
  78. VideoAddon="-bsf:v h264_mp4toannexb"
  79. else
  80. if [ "$BitRate" -gt "3500000" ]; then
  81. BitRadio="${ForceBitRadio}"
  82. BitRate=3000000
  83. else
  84. ForceRate="${BitRate}"
  85. BitRate=`awk 'BEGIN{print '${ForceRate}' * '${ForceBitRadio}'}' |cut -d'.' -f1`
  86. fi
  87. echo "media bitrate(new): ${BitRate}"
  88. ForceMaxRate=`awk 'BEGIN{print '${ForceRate}' * '${ForceMaxRadio}'}' |cut -d'.' -f1`
  89. ForceBuf=`awk 'BEGIN{print '${ForceRate}' / '${ForceMaxRadio}'}' |cut -d'.' -f1`
  90. VideoAddon="-b:v ${ForceRate} -maxrate ${ForceMaxRate} -bufsize ${ForceBuf}"
  91. fi
  92. fi
  93. if [ "$ForceH264" -le 1 ]; then
  94. VideoTime=`awk 'BEGIN{print ('${MaxSize}' * 1024 * 1024 * 8) / ('${BitRate}' * '${BitRadio}') }' |cut -d'.' -f1`
  95. if [ -n "$VideoTime" ]; then
  96. if [ "${BitRate}" -gt 3500000 ]; then
  97. MaxTime=5
  98. elif [ "${BitRate}" -gt 3000000 ]; then
  99. MaxTime=7
  100. fi
  101. if [ "$VideoTime" -gt "$MaxTime" ]; then
  102. VideoTime="$MaxTime"
  103. fi
  104. else
  105. exit 1
  106. fi
  107. fi
  108. echo "media segment time: ${VideoTime}"
  109. ffmpeg -v info -i "${Media}" -vcodec ${VideoCode} -acodec aac -strict experimental ${VideoAddon} -map 0:v:0 -map 0:a? -f segment -segment_list "${OutPutM3u8}" -segment_time "${VideoTime}" "${MediaFolder}/output_%04d.ts"
  110. if [ $? -ne 0 ]; then
  111. exit 1
  112. else
  113. cp -rf "${OutPutM3u8}" "${OutPutM3u8Bak}"
  114. fi
  115. else
  116. cp -rf "${OutPutM3u8Bak}" "${OutPutM3u8}"
  117. fi
  118. ## upload
  119. echo "start upload..."
  120. if [ -e "${ScriptDir}/${Uploader}" ]; then
  121. bash "${ScriptDir}/${Uploader}" "${MediaFolder}" |tee -a "${OutPutLog}"
  122. ## mod m3u8
  123. if [ -f "${ScriptDir}/${M3u8mod}" ]; then
  124. bash "${ScriptDir}/${M3u8mod}" "${OutPutLog}" "${OutPutM3u8}"
  125. fi
  126. fi
  127. # check
  128. echo "check upload..."
  129. function ForceVBR(){
  130. fsName="$1"
  131. loopTimes="$2"
  132. [ -n "${fsName}" ] && [ -f "${fsName}" ] || return
  133. [ `du -s -k "${fsName}" |cut -f1` -le `awk 'BEGIN{print '${MaxSize}' * 1024}' |cut -d'.' -f1` ] && return
  134. NewFsName="${fsName}_New.ts"
  135. cp -rf "${fsName}" "${NewFsName}"
  136. LowerRadio=`awk 'BEGIN{print 0.85 ** '${loopTimes}'}'`
  137. NewForceRate=`awk 'BEGIN{print '${ForceRate}' * '${LowerRadio}'}' |cut -d'.' -f1`
  138. NewForceMaxRate=`awk 'BEGIN{print '${NewForceRate}' * '${ForceMaxRadio}'}' |cut -d'.' -f1`
  139. NewForceBuf=`awk 'BEGIN{print '${NewForceRate}' / '${ForceMaxRadio}'}' |cut -d'.' -f1`
  140. VideoAddon="-b:v ${NewForceRate} -maxrate ${NewForceMaxRate} -bufsize ${NewForceBuf}"
  141. ffmpeg -y -v info -i "${NewFsName}" -copyts -vsync 0 -muxdelay 0 -vcodec h264 -acodec copy -strict experimental -bsf:v h264_mp4toannexb ${VideoAddon} -f mpegts "${fsName}"
  142. [ -f "${NewFsName}" ] && [ -f "${fsName}" ] && rm -rf "${NewFsName}"
  143. }
  144. for((i=0; i<$MaxCheck; i++)); do
  145. BadCheck=`grep -v "^#\|^https\?://" "${OutPutM3u8}"`
  146. [ -n "$BadCheck" ] || break
  147. for Item in `echo "$BadCheck"`; do
  148. if [ -f "${Item}" ]; then
  149. BadItem="${Item}"
  150. elif [ -f "${MediaFolder}/${Item}" ]; then
  151. BadItem="${MediaFolder}/${Item}"
  152. else
  153. echo "Error: not found '${Item}'."
  154. exit 1
  155. fi
  156. ForceVBR "${BadItem}" "${i}"
  157. bash "${ScriptDir}/${Uploader}" "${BadItem}" |tee -a "${OutPutLog}"
  158. done
  159. sed -i '/;\ NULL_/d' "${OutPutLog}"
  160. ## mod m3u8
  161. if [ -f "${ScriptDir}/${M3u8mod}" ]; then
  162. bash "${ScriptDir}/${M3u8mod}" "${OutPutLog}" "${OutPutM3u8}"
  163. fi
  164. done
  165. # publish
  166. if [ -f "${ScriptDir}/${Publish}" ]; then
  167. echo "publish ..."
  168. bash "${ScriptDir}/${Publish}" "${OutPutM3u8}"
  169. fi
  170. # clear
  171. if [ "$AutoClear" != 0 ]; then
  172. rm -rf "${OutPutLog}"
  173. rm -rf "${MediaFolder}"
  174. rm -rf "${OutPutM3u8Bak}"
  175. fi