Recherche avancée

Médias (1)

Mot : - Tags -/bug

Autres articles (83)

  • Support de tous types de médias

    10 avril 2011

    Contrairement à beaucoup de logiciels et autres plate-formes modernes de partage de documents, MediaSPIP a l’ambition de gérer un maximum de formats de documents différents qu’ils soient de type : images (png, gif, jpg, bmp et autres...) ; audio (MP3, Ogg, Wav et autres...) ; vidéo (Avi, MP4, Ogv, mpg, mov, wmv et autres...) ; contenu textuel, code ou autres (open office, microsoft office (tableur, présentation), web (html, css), LaTeX, Google Earth) (...)

  • Les tâches Cron régulières de la ferme

    1er décembre 2010, par

    La gestion de la ferme passe par l’exécution à intervalle régulier de plusieurs tâches répétitives dites Cron.
    Le super Cron (gestion_mutu_super_cron)
    Cette tâche, planifiée chaque minute, a pour simple effet d’appeler le Cron de l’ensemble des instances de la mutualisation régulièrement. Couplée avec un Cron système sur le site central de la mutualisation, cela permet de simplement générer des visites régulières sur les différents sites et éviter que les tâches des sites peu visités soient trop (...)

  • Les statuts des instances de mutualisation

    13 mars 2010, par

    Pour des raisons de compatibilité générale du plugin de gestion de mutualisations avec les fonctions originales de SPIP, les statuts des instances sont les mêmes que pour tout autre objets (articles...), seuls leurs noms dans l’interface change quelque peu.
    Les différents statuts possibles sont : prepa (demandé) qui correspond à une instance demandée par un utilisateur. Si le site a déjà été créé par le passé, il est passé en mode désactivé. publie (validé) qui correspond à une instance validée par un (...)

Sur d’autres sites (7511)

  • How to play and seek fragmented MP4 audio using MSE SourceBuffer ?

    29 juin 2024, par Stefan Falk

    Note :

    


    


    If you end up here, you might want to take a look at shaka-player and the accompanying shaka-streamer. Use it. Don't implement this yourself unless you really have to.

    


    


    I am trying for quite some time now to be able to play an audio track on Chrome, Firefox, Safari, etc. but I keep hitting brick walls. My problem is currently that I am just not able to seek within a fragmented MP4 (or MP3).

    


    At the moment I am converting audio files such as MP3 to fragmented MP4 (fMP4) and send them chunk-wise to the client. What I do is defining a CHUNK_DURACTION_SEC (chunk duration in seconds) and compute a chunk size like this :

    


    chunksTotal = Math.ceil(this.track.duration / CHUNK_DURATION_SEC);
chunkSize = Math.ceil(this.track.fileSize / this.chunksTotal);


    


    With this I partition the audio file and can fetch it entirely jumping chunkSize-many bytes for each chunk :

    


    -----------------------------------------
| chunk 1 | chunk 2 |   ...   | chunk n |
-----------------------------------------


    


    How audio files are converted to fMP4

    


    ffmpeg -i input.mp3 -acodec aac -b:a 256k -f mp4 \
       -movflags faststart+frag_every_frame+empty_moov+default_base_moof \
        output.mp4


    


    This seems to work with Chrome and Firefox (so far).

    


    How chunks are appended

    


    After following this example, and realizing that it's simply not working as it is explained here, I threw it away and started over from scratch. Unfortunately without success. It's still not working.

    


    The following code is supposed to play a track from the very beginning to the very end. However, I also need to be able to seek. So far, this is simply not working. Seeking will just stop the audio after the seeking event got triggered.

    


    The code

    


    /* Desired chunk duration in seconds. */&#xA;const CHUNK_DURATION_SEC = 20;&#xA;&#xA;const AUDIO_EVENTS = [&#xA;  &#x27;ended&#x27;,&#xA;  &#x27;error&#x27;,&#xA;  &#x27;play&#x27;,&#xA;  &#x27;playing&#x27;,&#xA;  &#x27;seeking&#x27;,&#xA;  &#x27;seeked&#x27;,&#xA;  &#x27;pause&#x27;,&#xA;  &#x27;timeupdate&#x27;,&#xA;  &#x27;canplay&#x27;,&#xA;  &#x27;loadedmetadata&#x27;,&#xA;  &#x27;loadstart&#x27;,&#xA;  &#x27;updateend&#x27;,&#xA;];&#xA;&#xA;&#xA;class ChunksLoader {&#xA;&#xA;  /** The total number of chunks for the track. */&#xA;  public readonly chunksTotal: number;&#xA;&#xA;  /** The length of one chunk in bytes */&#xA;  public readonly chunkSize: number;&#xA;&#xA;  /** Keeps track of requested chunks. */&#xA;  private readonly requested: boolean[];&#xA;&#xA;  /** URL of endpoint for fetching audio chunks. */&#xA;  private readonly url: string;&#xA;&#xA;  constructor(&#xA;    private track: Track,&#xA;    private sourceBuffer: SourceBuffer,&#xA;    private logger: NGXLogger,&#xA;  ) {&#xA;&#xA;    this.chunksTotal = Math.ceil(this.track.duration / CHUNK_DURATION_SEC);&#xA;    this.chunkSize = Math.ceil(this.track.fileSize / this.chunksTotal);&#xA;&#xA;    this.requested = [];&#xA;    for (let i = 0; i &lt; this.chunksTotal; i&#x2B;&#x2B;) {&#xA;      this.requested[i] = false;&#xA;    }&#xA;&#xA;    this.url = `${environment.apiBaseUrl}/api/tracks/${this.track.id}/play`;&#xA;  }&#xA;&#xA;  /**&#xA;   * Fetch the first chunk.&#xA;   */&#xA;  public begin() {&#xA;    this.maybeFetchChunk(0);&#xA;  }&#xA;&#xA;  /**&#xA;   * Handler for the "timeupdate" event. Checks if the next chunk should be fetched.&#xA;   *&#xA;   * @param currentTime&#xA;   *  The current time of the track which is currently played.&#xA;   */&#xA;  public handleOnTimeUpdate(currentTime: number) {&#xA;&#xA;    const nextChunkIndex = Math.floor(currentTime / CHUNK_DURATION_SEC) &#x2B; 1;&#xA;    const hasAllChunks = this.requested.every(val => !!val);&#xA;&#xA;    if (nextChunkIndex === (this.chunksTotal - 1) &amp;&amp; hasAllChunks) {&#xA;      this.logger.debug(&#x27;Last chunk. Calling mediaSource.endOfStream();&#x27;);&#xA;      return;&#xA;    }&#xA;&#xA;    if (this.requested[nextChunkIndex] === true) {&#xA;      return;&#xA;    }&#xA;&#xA;    if (currentTime &lt; CHUNK_DURATION_SEC * (nextChunkIndex - 1 &#x2B; 0.25)) {&#xA;      return;&#xA;    }&#xA;&#xA;    this.maybeFetchChunk(nextChunkIndex);&#xA;  }&#xA;&#xA;  /**&#xA;   * Fetches the chunk if it hasn&#x27;t been requested yet. After the request finished, the returned&#xA;   * chunk gets appended to the SourceBuffer-instance.&#xA;   *&#xA;   * @param chunkIndex&#xA;   *  The chunk to fetch.&#xA;   */&#xA;  private maybeFetchChunk(chunkIndex: number) {&#xA;&#xA;    const start = chunkIndex * this.chunkSize;&#xA;    const end = start &#x2B; this.chunkSize - 1;&#xA;&#xA;    if (this.requested[chunkIndex] == true) {&#xA;      return;&#xA;    }&#xA;&#xA;    this.requested[chunkIndex] = true;&#xA;&#xA;    if ((end - start) == 0) {&#xA;      this.logger.warn(&#x27;Nothing to fetch.&#x27;);&#xA;      return;&#xA;    }&#xA;&#xA;    const totalKb = ((end - start) / 1000).toFixed(2);&#xA;    this.logger.debug(`Starting to fetch bytes ${start} to ${end} (total ${totalKb} kB). Chunk ${chunkIndex &#x2B; 1} of ${this.chunksTotal}`);&#xA;&#xA;    const xhr = new XMLHttpRequest();&#xA;    xhr.open(&#x27;get&#x27;, this.url);&#xA;    xhr.setRequestHeader(&#x27;Authorization&#x27;, `Bearer ${AuthenticationService.getJwtToken()}`);&#xA;    xhr.setRequestHeader(&#x27;Range&#x27;, &#x27;bytes=&#x27; &#x2B; start &#x2B; &#x27;-&#x27; &#x2B; end);&#xA;    xhr.responseType = &#x27;arraybuffer&#x27;;&#xA;    xhr.onload = () => {&#xA;      this.logger.debug(`Range ${start} to ${end} fetched`);&#xA;      this.logger.debug(`Requested size:        ${end - start &#x2B; 1}`);&#xA;      this.logger.debug(`Fetched size:          ${xhr.response.byteLength}`);&#xA;      this.logger.debug(&#x27;Appending chunk to SourceBuffer.&#x27;);&#xA;      this.sourceBuffer.appendBuffer(xhr.response);&#xA;    };&#xA;    xhr.send();&#xA;  };&#xA;&#xA;}&#xA;&#xA;export enum StreamStatus {&#xA;  NOT_INITIALIZED,&#xA;  INITIALIZING,&#xA;  PLAYING,&#xA;  SEEKING,&#xA;  PAUSED,&#xA;  STOPPED,&#xA;  ERROR&#xA;}&#xA;&#xA;export class PlayerState {&#xA;  status: StreamStatus = StreamStatus.NOT_INITIALIZED;&#xA;}&#xA;&#xA;&#xA;/**&#xA; *&#xA; */&#xA;@Injectable({&#xA;  providedIn: &#x27;root&#x27;&#xA;})&#xA;export class MediaSourcePlayerService {&#xA;&#xA;  public track: Track;&#xA;&#xA;  private mediaSource: MediaSource;&#xA;&#xA;  private sourceBuffer: SourceBuffer;&#xA;&#xA;  private audioObj: HTMLAudioElement;&#xA;&#xA;  private chunksLoader: ChunksLoader;&#xA;&#xA;  private state: PlayerState = new PlayerState();&#xA;&#xA;  private state$ = new BehaviorSubject<playerstate>(this.state);&#xA;&#xA;  public stateChange = this.state$.asObservable();&#xA;&#xA;  private currentTime$ = new BehaviorSubject<number>(null);&#xA;&#xA;  public currentTimeChange = this.currentTime$.asObservable();&#xA;&#xA;  constructor(&#xA;    private httpClient: HttpClient,&#xA;    private logger: NGXLogger&#xA;  ) {&#xA;  }&#xA;&#xA;  get canPlay() {&#xA;    const state = this.state$.getValue();&#xA;    const status = state.status;&#xA;    return status == StreamStatus.PAUSED;&#xA;  }&#xA;&#xA;  get canPause() {&#xA;    const state = this.state$.getValue();&#xA;    const status = state.status;&#xA;    return status == StreamStatus.PLAYING || status == StreamStatus.SEEKING;&#xA;  }&#xA;&#xA;  public playTrack(track: Track) {&#xA;    this.logger.debug(&#x27;playTrack&#x27;);&#xA;    this.track = track;&#xA;    this.startPlayingFrom(0);&#xA;  }&#xA;&#xA;  public play() {&#xA;    this.logger.debug(&#x27;play()&#x27;);&#xA;    this.audioObj.play().then();&#xA;  }&#xA;&#xA;  public pause() {&#xA;    this.logger.debug(&#x27;pause()&#x27;);&#xA;    this.audioObj.pause();&#xA;  }&#xA;&#xA;  public stop() {&#xA;    this.logger.debug(&#x27;stop()&#x27;);&#xA;    this.audioObj.pause();&#xA;  }&#xA;&#xA;  public seek(seconds: number) {&#xA;    this.logger.debug(&#x27;seek()&#x27;);&#xA;    this.audioObj.currentTime = seconds;&#xA;  }&#xA;&#xA;  private startPlayingFrom(seconds: number) {&#xA;    this.logger.info(`Start playing from ${seconds.toFixed(2)} seconds`);&#xA;    this.mediaSource = new MediaSource();&#xA;    this.mediaSource.addEventListener(&#x27;sourceopen&#x27;, this.onSourceOpen);&#xA;&#xA;    this.audioObj = document.createElement(&#x27;audio&#x27;);&#xA;    this.addEvents(this.audioObj, AUDIO_EVENTS, this.handleEvent);&#xA;    this.audioObj.src = URL.createObjectURL(this.mediaSource);&#xA;&#xA;    this.audioObj.play().then();&#xA;  }&#xA;&#xA;  private onSourceOpen = () => {&#xA;&#xA;    this.logger.debug(&#x27;onSourceOpen&#x27;);&#xA;&#xA;    this.mediaSource.removeEventListener(&#x27;sourceopen&#x27;, this.onSourceOpen);&#xA;    this.mediaSource.duration = this.track.duration;&#xA;&#xA;    this.sourceBuffer = this.mediaSource.addSourceBuffer(&#x27;audio/mp4; codecs="mp4a.40.2"&#x27;);&#xA;    // this.sourceBuffer = this.mediaSource.addSourceBuffer(&#x27;audio/mpeg&#x27;);&#xA;&#xA;    this.chunksLoader = new ChunksLoader(&#xA;      this.track,&#xA;      this.sourceBuffer,&#xA;      this.logger&#xA;    );&#xA;&#xA;    this.chunksLoader.begin();&#xA;  };&#xA;&#xA;  private handleEvent = (e) => {&#xA;&#xA;    const currentTime = this.audioObj.currentTime.toFixed(2);&#xA;    const totalDuration = this.track.duration.toFixed(2);&#xA;    this.logger.warn(`MediaSource event: ${e.type} (${currentTime} of ${totalDuration} sec)`);&#xA;&#xA;    this.currentTime$.next(this.audioObj.currentTime);&#xA;&#xA;    const currentStatus = this.state$.getValue();&#xA;&#xA;    switch (e.type) {&#xA;      case &#x27;playing&#x27;:&#xA;        currentStatus.status = StreamStatus.PLAYING;&#xA;        this.state$.next(currentStatus);&#xA;        break;&#xA;      case &#x27;pause&#x27;:&#xA;        currentStatus.status = StreamStatus.PAUSED;&#xA;        this.state$.next(currentStatus);&#xA;        break;&#xA;      case &#x27;timeupdate&#x27;:&#xA;        this.chunksLoader.handleOnTimeUpdate(this.audioObj.currentTime);&#xA;        break;&#xA;      case &#x27;seeking&#x27;:&#xA;        currentStatus.status = StreamStatus.SEEKING;&#xA;        this.state$.next(currentStatus);&#xA;        if (this.mediaSource.readyState == &#x27;open&#x27;) {&#xA;          this.sourceBuffer.abort();&#xA;        }&#xA;        this.chunksLoader.handleOnTimeUpdate(this.audioObj.currentTime);&#xA;        break;&#xA;    }&#xA;  };&#xA;&#xA;  private addEvents(obj, events, handler) {&#xA;    events.forEach(event => obj.addEventListener(event, handler));&#xA;  }&#xA;&#xA;}&#xA;</number></playerstate>

    &#xA;

    Running it will give me the following output :

    &#xA;

    enter image description here

    &#xA;

    &#xA;

    Apologies for the screenshot but it's not possible to just copy the output without all the stack traces in Chrome.

    &#xA;

    &#xA;

    What I also tried was following this example and call sourceBuffer.abort() but that didn't work. It looks more like a hack that used to work years ago but it's still referenced in the docs (see "Example" -> "You can see something similar in action in Nick Desaulnier's bufferWhenNeeded demo ..").

    &#xA;

    case &#x27;seeking&#x27;:&#xA;  currentStatus.status = StreamStatus.SEEKING;&#xA;  this.state$.next(currentStatus);        &#xA;  if (this.mediaSource.readyState === &#x27;open&#x27;) {&#xA;    this.sourceBuffer.abort();&#xA;  } &#xA;  break;&#xA;

    &#xA;

    Trying with MP3

    &#xA;

    I have tested the above code under Chrome by converting tracks to MP3 :

    &#xA;

    ffmpeg -i input.mp3 -acodec aac -b:a 256k -f mp3 output.mp3&#xA;

    &#xA;

    and creating a SourceBuffer using audio/mpeg as type :

    &#xA;

    this.mediaSource.addSourceBuffer(&#x27;audio/mpeg&#x27;)&#xA;

    &#xA;

    I have the same problem when seeking.

    &#xA;

    The issue wihout seeking

    &#xA;

    The above code has another issue :

    &#xA;

    After two minutes of playing, the audio playback starts to stutter and comes to a halt prematurely. So, the audio plays up to a point and then it stops without any obvious reason.

    &#xA;

    For whatever reason there is another canplay and playing event. A few seconds after, the audio simply stops..

    &#xA;

    enter image description here

    &#xA;

  • Audio Video Mixing - Sync issue in Android with FFMPEG, Media Codec in different devices

    24 novembre 2020, par khushbu

    I have already tried everything for Audio Video mixing and it's not working perfectly as in processing while mixing audio into the recorded video, sometimes the audio is ahead of video and vice-versa.

    &#xA;

    Using FFMPEG :

    &#xA;

    This is for add an Audio file to the Video file and generated the final Video where audio is replaced in the video.

    &#xA;

    val cmd ="-i $inputVideoPath -i ${inputAudio.absolutePath} -map 0:v -map 1:a -c:v copy -shortest ${outputVideo.absolutePath}"&#xA;

    &#xA;

    After generating the final video, found some delay based on device performance so added delay in the below two cases :

    &#xA;

    1)Added delay in Audio if audio is ahead of the video.

    &#xA;

    val  cmd =  "-i ${tmpVideo.absolutePath} -itsoffset $hms -i ${tmpVideo.absolutePath} -map 0:v -map 1:a -c copy -preset veryfast ${createdVideo1?.absolutePath}"&#xA;

    &#xA;

    2)Added delay in Video if the video is ahead of the audio.

    &#xA;

    val  cmd =   "-i ${tmpVideo.absolutePath} -itsoffset $hms -i ${tmpVideo.absolutePath} -map 1:v -map 0:a -c copy -preset veryfast ${createdVideo1?.absolutePath}"&#xA;

    &#xA;

    NOTE : Here $hms is delay in 00:00:00.000 formate

    &#xA;

    but still, it's not working on all the devices like readmi, oneplus etc.

    &#xA;

    Using Media Codec :

    &#xA;

    Found some better performance in this solution but still not working on all the devices.

    &#xA;

    In this process, It's supporting .aac format so first if the user selected .mp3 formate than i have to convert it into .aac format using the below function :

    &#xA;

    fun Convert_Mp3_to_acc() {&#xA;&#xA;   &#xA;    AndroidAudioConverter.load(requireActivity(), object : ILoadCallback {&#xA;        override fun onSuccess() {&#xA;&#xA;            val callback: IConvertCallback = object : IConvertCallback {&#xA;                override fun onSuccess(convertedFile: File) {&#xA;                    toggleLoader(false)&#xA;                    audioLink = convertedFile.absolutePath&#xA;                    append()&#xA;                 &#xA;&#xA;                }&#xA;&#xA;                override fun onFailure(error: java.lang.Exception) {&#xA;                    toggleLoader(false)&#xA;                    Toast.makeText(requireActivity(), "" &#x2B; error, Toast.LENGTH_SHORT).show()&#xA;                }&#xA;            }&#xA;            AndroidAudioConverter.with(requireActivity())&#xA;                .setFile(File(audioLink))&#xA;                .setFormat(AudioFormat.AAC)&#xA;                .setCallback(callback)&#xA;                .convert()&#xA;        }&#xA;&#xA;        override fun onFailure(error: java.lang.Exception) {&#xA;            toggleLoader(false)&#xA;        }&#xA;    })&#xA;}&#xA;

    &#xA;

    After successful conversion from .mp3 to .aac formate, It's extracting audio track and video track for merge

    &#xA;

     private fun append(): Boolean {&#xA;&#xA;    val progressDialog = ProgressDialog(requireContext())&#xA;    Thread {&#xA;        requireActivity().runOnUiThread {&#xA;            progressDialog.setMessage("Please wait..")&#xA;            progressDialog.show()&#xA;        }&#xA;        val video_list = ArrayList<string>()&#xA;        for (i in videopaths.indices) {&#xA;            val file: File = File(videopaths.get(i))&#xA;            if (file.exists()) {&#xA;                val retriever = MediaMetadataRetriever()&#xA;                retriever.setDataSource(requireActivity(), Uri.fromFile(file))&#xA;                val hasVideo =&#xA;                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO)&#xA;                val isVideo = "yes" == hasVideo&#xA;                if (isVideo /*&amp;&amp; file.length() > 1000*/) {&#xA;                    Log.d("resp", videopaths.get(i))&#xA;                    video_list.add(videopaths.get(i))&#xA;                }&#xA;            }&#xA;        }&#xA;        try {&#xA;            val inMovies = arrayOfNulls<movie>(video_list.size)&#xA;            for (i in video_list.indices) {&#xA;                inMovies[i] = MovieCreator.build(video_list[i])&#xA;            }&#xA;            val videoTracks: MutableList<track> =&#xA;                LinkedList()&#xA;            val audioTracks: MutableList<track> =&#xA;                LinkedList()&#xA;            for (m in inMovies) {&#xA;                for (t in m!!.tracks) {&#xA;                    if (t.handler == "soun") {&#xA;                        audioTracks.add(t)&#xA;                    }&#xA;                    if (t.handler == "vide") {&#xA;                        videoTracks.add(t)&#xA;                    }&#xA;                }&#xA;            }&#xA;            val result = Movie()&#xA;            if (audioTracks.size > 0) {&#xA;                result.addTrack(AppendTrack(*audioTracks.toTypedArray()))&#xA;            }&#xA;            if (videoTracks.size > 0) {&#xA;                result.addTrack(AppendTrack(*videoTracks.toTypedArray()))&#xA;            }&#xA;            val out = DefaultMp4Builder().build(result)&#xA;            var outputFilePath: String? = null&#xA;            outputFilePath =  Variables.outputfile&#xA;&#xA;            /*if (audio != null) {&#xA;                Variables.outputfile&#xA;            } else {&#xA;                Variables.outputfile2&#xA;            }*/&#xA;&#xA;            val fos = FileOutputStream(File(outputFilePath))&#xA;            out.writeContainer(fos.channel)&#xA;            fos.close()&#xA;&#xA;            requireActivity().runOnUiThread {&#xA;                progressDialog.dismiss()&#xA;&#xA;                Merge_withAudio()&#xA;&#xA;                /* if (audio != null) else {&#xA;                     //Go_To_preview_Activity()&#xA;                 }*/&#xA;            }&#xA;        } catch (e: java.lang.Exception) {&#xA;        }&#xA;    }.start()&#xA;&#xA;    return true&#xA;}&#xA;</track></track></movie></string>

    &#xA;

    This will add the selected audio with the recorded video

    &#xA;

    fun Merge_withAudio() {&#xA;    val root = Environment.getExternalStorageDirectory().toString()&#xA;&#xA;    // Uri mediaPath = Uri.parse("android.resource://" &#x2B; getPackageName() &#x2B; "/" &#x2B; R.raw.file_copy);&#xA;    //String audio_file =Variables.app_folder&#x2B;Variables.SelectedAudio_AAC;&#xA;&#xA;    //String filename = "android.resource://" &#x2B; getPackageName() &#x2B; "/raw/file_copy.aac";&#xA;    val audio_file: String = audioLink!!&#xA;    Log.e("Merge ", audio_file)&#xA;    val video = "$root/output.mp4"&#xA;&#xA;    val bundle=Bundle()&#xA;    bundle.putString("FinalVideo", createdVideo?.absolutePath)&#xA;&#xA;    val merge_video_audio = Merge_Video_Audio(this, bundle, object : AsyncResponse {&#xA;        override fun processFinish(output: Bundle?) {&#xA;&#xA;            requireActivity().runOnUiThread {&#xA;                finalVideo = bundle.getString("FinalVideo")&#xA;                createdVideo = File(finalVideo)&#xA;&#xA;                Log.e("Final Path ", finalVideo)&#xA;&#xA;                createThumb {&#xA;                    setUpExoPlayer()&#xA;                }&#xA;            }&#xA;&#xA;        }&#xA;    })&#xA;    merge_video_audio.doInBackground(audio_file, video, createdVideo?.absolutePath)&#xA;}&#xA;&#xA;&#xA; public class Merge_Video_Audio extends AsyncTask {&#xA;&#xA;   ProgressDialog progressDialog;&#xA;   RecentCompletedVideoFragment context;&#xA;   public AsyncResponse delegate = null;&#xA;&#xA;&#xA;Bundle bundleValue;&#xA;&#xA;String audio,video,output;&#xA;&#xA;public Merge_Video_Audio(RecentCompletedVideoFragment context, Bundle bundle , AsyncResponse delegate ){&#xA;    this.context=context;&#xA;    this.bundleValue=bundle;&#xA;    this.delegate=delegate;&#xA;    progressDialog=new ProgressDialog(context.requireContext());&#xA;    progressDialog.setMessage("Please Wait...");&#xA;}&#xA;&#xA;@Override&#xA;protected void onPreExecute() {&#xA;    super.onPreExecute();&#xA;}&#xA;&#xA;@Override&#xA;public String doInBackground(String... strings) {&#xA;    try {&#xA;        progressDialog.show();&#xA;    }catch (Exception e){&#xA;&#xA;    }&#xA;     audio=strings[0];&#xA;     video=strings[1];&#xA;     output=strings[2];&#xA;&#xA;     Log.d("resp",audio&#x2B;"----"&#x2B;video&#x2B;"-----"&#x2B;output);&#xA;&#xA;    Thread thread = new Thread(runnable);&#xA;    thread.start();&#xA;&#xA;    return null;&#xA;}&#xA;&#xA;&#xA;@Override&#xA;protected void onPostExecute(String s) {&#xA;    super.onPostExecute(s);&#xA;    Log.e("On Post Execute ", "True");&#xA;&#xA;&#xA;}&#xA;&#xA;&#xA;   public void Go_To_preview_Activity(){&#xA;&#xA;    delegate.processFinish(bundleValue);&#xA;   }&#xA;&#xA;  public Track CropAudio(String videopath, Track fullAudio){&#xA;    try {&#xA;&#xA;        IsoFile isoFile = new IsoFile(videopath);&#xA;&#xA;        double lengthInSeconds = (double)&#xA;                isoFile.getMovieBox().getMovieHeaderBox().getDuration() /&#xA;                isoFile.getMovieBox().getMovieHeaderBox().getTimescale();&#xA;&#xA;&#xA;        Track audioTrack = (Track) fullAudio;&#xA;&#xA;&#xA;        double startTime1 = 0;&#xA;        double endTime1 = lengthInSeconds;&#xA;&#xA;&#xA;        long currentSample = 0;&#xA;        double currentTime = 0;&#xA;        double lastTime = -1;&#xA;        long startSample1 = -1;&#xA;        long endSample1 = -1;&#xA;&#xA;&#xA;        for (int i = 0; i &lt; audioTrack.getSampleDurations().length; i&#x2B;&#x2B;) {&#xA;&#xA;            long delta = audioTrack.getSampleDurations()[i];&#xA;&#xA;            if (currentTime > lastTime &amp;&amp; currentTime &lt;= startTime1) {&#xA;                // current sample is still before the new starttime&#xA;                startSample1 = currentSample;&#xA;            }&#xA;            if (currentTime > lastTime &amp;&amp; currentTime &lt;= endTime1) {&#xA;                // current sample is after the new start time and still before the new endtime&#xA;                endSample1 = currentSample;&#xA;            }&#xA;&#xA;            lastTime = currentTime;&#xA;            currentTime &#x2B;= (double) delta / (double) audioTrack.getTrackMetaData().getTimescale();&#xA;            currentSample&#x2B;&#x2B;;&#xA;        }&#xA;&#xA;        CroppedTrack cropperAacTrack = new CroppedTrack(fullAudio, startSample1, endSample1);&#xA;&#xA;        return cropperAacTrack;&#xA;&#xA;    } catch (IOException e) {&#xA;        e.printStackTrace();&#xA;    }&#xA;&#xA;    return fullAudio;&#xA;}&#xA;&#xA;&#xA;&#xA;  public Runnable runnable =new Runnable() {&#xA;    @Override&#xA;    public void run() {&#xA;&#xA;        try {&#xA;&#xA;            Movie m = MovieCreator.build(video);&#xA;&#xA;&#xA;            List nuTracks = new ArrayList&lt;>();&#xA;&#xA;            for (Track t : m.getTracks()) {&#xA;                if (!"soun".equals(t.getHandler())) {&#xA;&#xA;                    Log.e("Track  ",t.getName());&#xA;                    nuTracks.add(t);&#xA;                }&#xA;            }&#xA;&#xA;            Log.e("Path ",audio.toString());&#xA;&#xA;&#xA;            try {&#xA;                // Track nuAudio = new AACTrackImpl();&#xA;                Track nuAudio = new AACTrackImpl(new FileDataSourceImpl(audio));&#xA;&#xA;                Track crop_track = CropAudio(video, nuAudio);&#xA;&#xA;                nuTracks.add(crop_track);&#xA;&#xA;                m.setTracks(nuTracks);&#xA;&#xA;                Container mp4file = new DefaultMp4Builder().build(m);&#xA;&#xA;                FileChannel fc = new FileOutputStream(new File(output)).getChannel();&#xA;                mp4file.writeContainer(fc);&#xA;                fc.close();&#xA;&#xA;            }catch (FileNotFoundException fnfe){&#xA;                fnfe.printStackTrace();&#xA;            }catch(IOException ioe){&#xA;                ioe.printStackTrace();&#xA;           }&#xA;&#xA;&#xA;            try {&#xA;&#xA;                progressDialog.dismiss();&#xA;            }catch (Exception e){&#xA;                Log.d("resp",e.toString());&#xA;&#xA;            }finally {&#xA;                Go_To_preview_Activity();&#xA;&#xA;            }&#xA;&#xA;        } catch (IOException e) {&#xA;            e.printStackTrace();&#xA;            Log.d("resp",e.toString());&#xA;&#xA;        }&#xA;&#xA;    }&#xA;&#xA; };&#xA;&#xA; }&#xA;

    &#xA;

    This solution is also not working in all the devices.

    &#xA;

    Can anyone suggest where i am going wrong or any solution for it ?

    &#xA;

  • ffmpeg : problems playing video on android

    25 novembre 2020, par Jonathan García

    (Translated) Hello ! I have the following problem. I concatenate multiple ts files and convert to mp4 with ffmpeg. I do this operation multiple times in an automated way, so I don't always check the results, but whenever I do, on the computer, the result obtained is as expected. However, some videos, when played on an Android device, are seen incorrectly in any application : Chrome, Firefox, Vlc, etc. The version of ffmpeg I use is the latest. This is the command I use :

    &#xA;

    ffmpeg.exe -hwaccel dxva2 -y -f concat -i list.txt -acodec copy -vcodec copy output.mp4 -preset normal

    &#xA;

    Results :

    &#xA;

    PC

    &#xA;

    Android

    &#xA;

    This is the output of ffmpeg :

    &#xA;

    ffmpeg version n4.3.1-26-gca55240b8c Copyright (c) 2000-2020 the FFmpeg developers&#xA;  built with gcc 9.3-win32 (GCC) 20200320&#xA;  configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --disable-w32threads --enable-pthreads --enable-iconv --enable-zlib --enable-libxml2 --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-opencl --enable-libvmaf --disable-vulkan --enable-libvorbis --enable-amf --enable-libaom --enable-avisynth --enable-libdav1d --enable-libdavs2 --enable-ffnvcodec --enable-cuda-llvm --disable-libglslang --enable-libass --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvpx --enable-libwebp --enable-libmfx --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librav1e --enable-librubberband --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libtwolame --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libzimg --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-libs=-lgomp&#xA;  libavutil      56. 51.100 / 56. 51.100&#xA;  libavcodec     58. 91.100 / 58. 91.100&#xA;  libavformat    58. 45.100 / 58. 45.100&#xA;  libavdevice    58. 10.100 / 58. 10.100&#xA;  libavfilter     7. 85.100 /  7. 85.100&#xA;  libswscale      5.  7.100 /  5.  7.100&#xA;  libswresample   3.  7.100 /  3.  7.100&#xA;  libpostproc    55.  7.100 / 55.  7.100&#xA;Trailing option(s) found in the command: may be ignored.&#xA;Input #0, concat, from &#x27;list.txt&#x27;:&#xA;  Duration: N/A, start: 0.000000, bitrate: N/A&#xA;    Stream #0:0: Data: timed_id3 (ID3  / 0x20334449)&#xA;    Stream #0:1: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, unknown/bt470bg/unknown, progressive), 320x568, 29.50 fps, 29.50 tbr, 90k tbn, 180k tbc&#xA;    Stream #0:2: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, mono, fltp, 64 kb/s&#xA;Output #0, mp4, to &#x27;output.mp4&#x27;:&#xA;  Metadata:&#xA;    encoder         : Lavf58.45.100&#xA;    Stream #0:0: Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, unknown/bt470bg/unknown, progressive), 320x568, q=2-31, 29.50 fps, 29.50 tbr, 90k tbn, 90k tbc&#xA;    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 64 kb/s&#xA;Stream mapping:&#xA;  Stream #0:1 -> #0:0 (copy)&#xA;  Stream #0:2 -> #0:1 (copy)&#xA;Press [q] to stop, [?] for help&#xA;frame= 9504 fps=8330 q=-1.0 Lsize=   24561kB time=00:07:42.26 bitrate= 435.3kbits/s speed= 405x&#xA;video:21200kB audio:3100kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.073735%&#xA;

    &#xA;

    Not all videos are "yuv420p (tv, unknown / bt470bg / unknown, progressive)", but this should not be the problem, since other videos with this information are seen correctly on Android.

    &#xA;

    To correct this type of video I do the following :

    &#xA;

    ffmpeg -y -f concat -i list.txt -c:v libx264 -preset slow -crf 22 -pix_fmt yuv420p -c:a aac -b:a 128k output.mp4

    &#xA;

    So I get the video to play correctly both on pc and Android. Unfortunately, automating the process by always using this last line occasionally causes problems (starting file 40MB, ending file> 1GB, more than 2 hours)

    &#xA;

    I would like, if possible, help me identify which videos will be viewed incorrectly on Android. Thank you very much in advance. Finally, this is the answer that ffmpeg gives when executing the line with which I fix the file :

    &#xA;

    ffmpeg version n4.3.1-26-gca55240b8c Copyright (c) 2000-2020 the FFmpeg developers&#xA;  built with gcc 9.3-win32 (GCC) 20200320&#xA;  configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --disable-w32threads --enable-pthreads --enable-iconv --enable-zlib --enable-libxml2 --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-opencl --enable-libvmaf --disable-vulkan --enable-libvorbis --enable-amf --enable-libaom --enable-avisynth --enable-libdav1d --enable-libdavs2 --enable-ffnvcodec --enable-cuda-llvm --disable-libglslang --enable-libass --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvpx --enable-libwebp --enable-libmfx --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librav1e --enable-librubberband --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libtwolame --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libzimg --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-libs=-lgomp&#xA;  libavutil      56. 51.100 / 56. 51.100&#xA;  libavcodec     58. 91.100 / 58. 91.100&#xA;  libavformat    58. 45.100 / 58. 45.100&#xA;  libavdevice    58. 10.100 / 58. 10.100&#xA;  libavfilter     7. 85.100 /  7. 85.100&#xA;  libswscale      5.  7.100 /  5.  7.100&#xA;  libswresample   3.  7.100 /  3.  7.100&#xA;  libpostproc    55.  7.100 / 55.  7.100&#xA;Input #0, concat, from &#x27;list.txt&#x27;:&#xA;  Duration: N/A, start: 0.000000, bitrate: N/A&#xA;    Stream #0:0: Data: timed_id3 (ID3  / 0x20334449)&#xA;    Stream #0:1: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(tv, unknown/bt470bg/unknown, progressive), 320x568, 29.50 fps, 29.50 tbr, 90k tbn, 180k tbc&#xA;    Stream #0:2: Audio: aac (LC) ([15][0][0][0] / 0x000F), 44100 Hz, mono, fltp, 64 kb/s&#xA;Stream mapping:&#xA;  Stream #0:1 -> #0:0 (h264 (native) -> h264 (libx264))&#xA;  Stream #0:2 -> #0:1 (aac (native) -> aac (native))&#xA;Press [q] to stop, [?] for help&#xA;[libx264 @ 000001efdbaee540] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2&#xA;[libx264 @ 000001efdbaee540] profile High, level 3.0, 4:2:0, 8-bit&#xA;[libx264 @ 000001efdbaee540] 264 - core 161 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=5 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=50 rc=crf mbtree=1 crf=22.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00&#xA;Output #0, mp4, to &#x27;d.mp4&#x27;:&#xA;  Metadata:&#xA;    encoder         : Lavf58.45.100&#xA;    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 320x568, q=-1--1, 29.50 fps, 15104 tbn, 29.50 tbc&#xA;    Metadata:&#xA;      encoder         : Lavc58.91.100 libx264&#xA;    Side data:&#xA;      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A&#xA;    Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 128 kb/s&#xA;    Metadata:&#xA;      encoder         : Lavc58.91.100 aac&#xA;More than 1000 frames duplicated    8960kB time=00:02:06.74 bitrate= 579.1kbits/s dup=999 drop=0 speed=15.7x&#xA;frame=13638 fps=468 q=-1.0 Lsize=   32033kB time=00:07:42.20 bitrate= 567.8kbits/s dup=4134 drop=0 speed=15.9x&#xA;video:25547kB audio:5995kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.557852%&#xA;[libx264 @ 000001efdbaee540] frame I:87    Avg QP:19.17  size: 12750&#xA;[libx264 @ 000001efdbaee540] frame P:4630  Avg QP:21.89  size:  4286&#xA;[libx264 @ 000001efdbaee540] frame B:8921  Avg QP:23.89  size:   583&#xA;[libx264 @ 000001efdbaee540] consecutive B-frames:  8.9%  8.6%  9.1% 73.4%&#xA;[libx264 @ 000001efdbaee540] mb I  I16..4: 12.2% 76.2% 11.6%&#xA;[libx264 @ 000001efdbaee540] mb P  I16..4:  3.7% 11.0%  0.8%  P16..4: 37.1% 16.2%  5.7%  0.0%  0.0%    skip:25.4%&#xA;[libx264 @ 000001efdbaee540] mb B  I16..4:  0.3%  0.9%  0.1%  B16..8: 30.4%  3.1%  0.3%  direct: 0.8%  skip:64.2%  L0:51.4% L1:44.3% BI: 4.3%&#xA;[libx264 @ 000001efdbaee540] 8x8 transform intra:71.2% inter:66.8%&#xA;[libx264 @ 000001efdbaee540] direct mvs  spatial:99.9% temporal:0.1%&#xA;[libx264 @ 000001efdbaee540] coded y,uvDC,uvAC intra: 52.5% 42.1% 5.5% inter: 9.7% 9.0% 0.3%&#xA;[libx264 @ 000001efdbaee540] i16 v,h,dc,p: 19% 21%  9% 50%&#xA;[libx264 @ 000001efdbaee540] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 22% 11% 13%  6%  9% 11%  9% 11%  8%&#xA;[libx264 @ 000001efdbaee540] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23%  9%  8%  6% 14% 14% 11%  9%  6%&#xA;[libx264 @ 000001efdbaee540] i8c dc,h,v,p: 46% 20% 23% 12%&#xA;[libx264 @ 000001efdbaee540] Weighted P-Frames: Y:2.9% UV:0.8%&#xA;[libx264 @ 000001efdbaee540] ref P L0: 72.3% 12.2% 11.3%  2.1%  1.9%  0.2%  0.0%&#xA;[libx264 @ 000001efdbaee540] ref B L0: 93.1%  5.5%  1.1%  0.3%&#xA;[libx264 @ 000001efdbaee540] ref B L1: 97.6%  2.4%&#xA;[libx264 @ 000001efdbaee540] kb/s:452.67&#xA;[aac @ 000001efdbaee9c0] Qavg: 10682.834&#xA;

    &#xA;